codacus commited on
Commit
47a1def
Β·
2 Parent(s): 7158ad6 00d871b

Merge remote-tracking branch 'upstream/main'

Browse files
README.md CHANGED
@@ -43,6 +43,9 @@ https://thinktank.ottomator.ai
43
  - βœ… Mobile friendly (@qwikode)
44
  - βœ… Better prompt enhancing (@SujalXplores)
45
  - βœ… Attach images to prompts (@atrokhym)
 
 
 
46
  - βœ… Detect package.json and commands to auto install & run preview for folder and git import (@wonderwhy-er)
47
  - βœ… Selection tool to target changes visually (@emcconnell)
48
  - ⬜ **HIGH PRIORITY** - Prevent bolt from rewriting files as often (file locking and diffs)
 
43
  - βœ… Mobile friendly (@qwikode)
44
  - βœ… Better prompt enhancing (@SujalXplores)
45
  - βœ… Attach images to prompts (@atrokhym)
46
+ - βœ… Added Git Clone button (@thecodacus)
47
+ - βœ… Git Import from url (@thecodacus)
48
+ - βœ… PromptLibrary to have different variations of prompts for different use cases (@thecodacus)
49
  - βœ… Detect package.json and commands to auto install & run preview for folder and git import (@wonderwhy-er)
50
  - βœ… Selection tool to target changes visually (@emcconnell)
51
  - ⬜ **HIGH PRIORITY** - Prevent bolt from rewriting files as often (file locking and diffs)
app/commit.json CHANGED
@@ -1 +1 @@
1
- { "commit": "eb1d5417e77e699e0489f09814e87fb5afed9dd5" , "version": "" }
 
1
+ { "commit": "de2cb43d170033c43a6cf436af02e033f66a7e4d" , "version": "" }
app/components/chat/BaseChat.tsx CHANGED
@@ -77,6 +77,8 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
77
  input = '',
78
  enhancingPrompt,
79
  handleInputChange,
 
 
80
  enhancePrompt,
81
  sendMessage,
82
  handleStop,
 
77
  input = '',
78
  enhancingPrompt,
79
  handleInputChange,
80
+
81
+ // promptEnhanced,
82
  enhancePrompt,
83
  sendMessage,
84
  handleStop,
app/components/chat/Chat.client.tsx CHANGED
@@ -93,7 +93,7 @@ export const ChatImpl = memo(
93
  const [uploadedFiles, setUploadedFiles] = useState<File[]>([]); // Move here
94
  const [imageDataList, setImageDataList] = useState<string[]>([]); // Move here
95
  const files = useStore(workbenchStore.files);
96
- const { activeProviders } = useSettings();
97
 
98
  const [model, setModel] = useState(() => {
99
  const savedModel = Cookies.get('selectedModel');
@@ -115,6 +115,7 @@ export const ChatImpl = memo(
115
  body: {
116
  apiKeys,
117
  files,
 
118
  },
119
  sendExtraMessageFields: true,
120
  onError: (error) => {
 
93
  const [uploadedFiles, setUploadedFiles] = useState<File[]>([]); // Move here
94
  const [imageDataList, setImageDataList] = useState<string[]>([]); // Move here
95
  const files = useStore(workbenchStore.files);
96
+ const { activeProviders, promptId } = useSettings();
97
 
98
  const [model, setModel] = useState(() => {
99
  const savedModel = Cookies.get('selectedModel');
 
115
  body: {
116
  apiKeys,
117
  files,
118
+ promptId,
119
  },
120
  sendExtraMessageFields: true,
121
  onError: (error) => {
app/components/settings/debug/DebugTab.tsx CHANGED
@@ -303,7 +303,7 @@ const checkProviderStatus = async (url: string | null, providerName: string): Pr
303
  };
304
 
305
  export default function DebugTab() {
306
- const { providers, latestBranch } = useSettings();
307
  const [activeProviders, setActiveProviders] = useState<ProviderStatus[]>([]);
308
  const [updateMessage, setUpdateMessage] = useState<string>('');
309
  const [systemInfo] = useState<SystemInfo>(getSystemInfo());
@@ -363,7 +363,7 @@ export default function DebugTab() {
363
  setIsCheckingUpdate(true);
364
  setUpdateMessage('Checking for updates...');
365
 
366
- const branchToCheck = latestBranch ? 'main' : 'stable';
367
  console.log(`[Debug] Checking for updates against ${branchToCheck} branch`);
368
 
369
  const localCommitResponse = await fetch(GITHUB_URLS.commitJson(branchToCheck));
@@ -391,7 +391,7 @@ export default function DebugTab() {
391
  } finally {
392
  setIsCheckingUpdate(false);
393
  }
394
- }, [isCheckingUpdate, latestBranch]);
395
 
396
  const handleCopyToClipboard = useCallback(() => {
397
  const debugInfo = {
@@ -408,7 +408,7 @@ export default function DebugTab() {
408
  })),
409
  Version: {
410
  hash: versionHash.slice(0, 7),
411
- branch: latestBranch ? 'main' : 'stable',
412
  },
413
  Timestamp: new Date().toISOString(),
414
  };
@@ -416,7 +416,7 @@ export default function DebugTab() {
416
  navigator.clipboard.writeText(JSON.stringify(debugInfo, null, 2)).then(() => {
417
  toast.success('Debug information copied to clipboard!');
418
  });
419
- }, [activeProviders, systemInfo, latestBranch]);
420
 
421
  return (
422
  <div className="p-4 space-y-6">
@@ -523,7 +523,7 @@ export default function DebugTab() {
523
  <p className="text-sm font-medium text-bolt-elements-textPrimary font-mono">
524
  {versionHash.slice(0, 7)}
525
  <span className="ml-2 text-xs text-bolt-elements-textSecondary">
526
- (v{versionTag || '0.0.1'}) - {latestBranch ? 'nightly' : 'stable'}
527
  </span>
528
  </p>
529
  </div>
 
303
  };
304
 
305
  export default function DebugTab() {
306
+ const { providers, isLatestBranch } = useSettings();
307
  const [activeProviders, setActiveProviders] = useState<ProviderStatus[]>([]);
308
  const [updateMessage, setUpdateMessage] = useState<string>('');
309
  const [systemInfo] = useState<SystemInfo>(getSystemInfo());
 
363
  setIsCheckingUpdate(true);
364
  setUpdateMessage('Checking for updates...');
365
 
366
+ const branchToCheck = isLatestBranch ? 'main' : 'stable';
367
  console.log(`[Debug] Checking for updates against ${branchToCheck} branch`);
368
 
369
  const localCommitResponse = await fetch(GITHUB_URLS.commitJson(branchToCheck));
 
391
  } finally {
392
  setIsCheckingUpdate(false);
393
  }
394
+ }, [isCheckingUpdate, isLatestBranch]);
395
 
396
  const handleCopyToClipboard = useCallback(() => {
397
  const debugInfo = {
 
408
  })),
409
  Version: {
410
  hash: versionHash.slice(0, 7),
411
+ branch: isLatestBranch ? 'main' : 'stable',
412
  },
413
  Timestamp: new Date().toISOString(),
414
  };
 
416
  navigator.clipboard.writeText(JSON.stringify(debugInfo, null, 2)).then(() => {
417
  toast.success('Debug information copied to clipboard!');
418
  });
419
+ }, [activeProviders, systemInfo, isLatestBranch]);
420
 
421
  return (
422
  <div className="p-4 space-y-6">
 
523
  <p className="text-sm font-medium text-bolt-elements-textPrimary font-mono">
524
  {versionHash.slice(0, 7)}
525
  <span className="ml-2 text-xs text-bolt-elements-textSecondary">
526
+ (v{versionTag || '0.0.1'}) - {isLatestBranch ? 'nightly' : 'stable'}
527
  </span>
528
  </p>
529
  </div>
app/components/settings/features/FeaturesTab.tsx CHANGED
@@ -1,10 +1,20 @@
1
  import React from 'react';
2
  import { Switch } from '~/components/ui/Switch';
 
3
  import { useSettings } from '~/lib/hooks/useSettings';
4
 
5
  export default function FeaturesTab() {
6
- const { debug, enableDebugMode, isLocalModel, enableLocalModels, enableEventLogs, latestBranch, enableLatestBranch } =
7
- useSettings();
 
 
 
 
 
 
 
 
 
8
 
9
  const handleToggle = (enabled: boolean) => {
10
  enableDebugMode(enabled);
@@ -27,7 +37,7 @@ export default function FeaturesTab() {
27
  Check for updates against the main branch instead of stable
28
  </p>
29
  </div>
30
- <Switch className="ml-auto" checked={latestBranch} onCheckedChange={enableLatestBranch} />
31
  </div>
32
  </div>
33
  </div>
@@ -37,10 +47,28 @@ export default function FeaturesTab() {
37
  <p className="text-sm text-bolt-elements-textSecondary mb-4">
38
  Disclaimer: Experimental features may be unstable and are subject to change.
39
  </p>
 
40
  <div className="flex items-center justify-between mb-2">
41
  <span className="text-bolt-elements-textPrimary">Experimental Providers</span>
42
  <Switch className="ml-auto" checked={isLocalModel} onCheckedChange={enableLocalModels} />
43
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  </div>
45
  </div>
46
  );
 
1
  import React from 'react';
2
  import { Switch } from '~/components/ui/Switch';
3
+ import { PromptLibrary } from '~/lib/common/prompt-library';
4
  import { useSettings } from '~/lib/hooks/useSettings';
5
 
6
  export default function FeaturesTab() {
7
+ const {
8
+ debug,
9
+ enableDebugMode,
10
+ isLocalModel,
11
+ enableLocalModels,
12
+ enableEventLogs,
13
+ isLatestBranch,
14
+ enableLatestBranch,
15
+ promptId,
16
+ setPromptId,
17
+ } = useSettings();
18
 
19
  const handleToggle = (enabled: boolean) => {
20
  enableDebugMode(enabled);
 
37
  Check for updates against the main branch instead of stable
38
  </p>
39
  </div>
40
+ <Switch className="ml-auto" checked={isLatestBranch} onCheckedChange={enableLatestBranch} />
41
  </div>
42
  </div>
43
  </div>
 
47
  <p className="text-sm text-bolt-elements-textSecondary mb-4">
48
  Disclaimer: Experimental features may be unstable and are subject to change.
49
  </p>
50
+
51
  <div className="flex items-center justify-between mb-2">
52
  <span className="text-bolt-elements-textPrimary">Experimental Providers</span>
53
  <Switch className="ml-auto" checked={isLocalModel} onCheckedChange={enableLocalModels} />
54
  </div>
55
+ <div className="flex items-start justify-between pt-4 mb-2 gap-2">
56
+ <div className="flex-1 max-w-[200px]">
57
+ <span className="text-bolt-elements-textPrimary">Prompt Library</span>
58
+ <p className="text-sm text-bolt-elements-textSecondary mb-4">
59
+ Choose a prompt from the library to use as the system prompt.
60
+ </p>
61
+ </div>
62
+ <select
63
+ value={promptId}
64
+ onChange={(e) => setPromptId(e.target.value)}
65
+ className="flex-1 p-2 ml-auto 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 text-sm min-w-[100px]"
66
+ >
67
+ {PromptLibrary.getList().map((x) => (
68
+ <option value={x.id}>{x.label}</option>
69
+ ))}
70
+ </select>
71
+ </div>
72
  </div>
73
  </div>
74
  );
app/lib/.server/llm/stream-text.ts CHANGED
@@ -1,10 +1,20 @@
1
  import { convertToCoreMessages, streamText as _streamText } from 'ai';
2
  import { getModel } from '~/lib/.server/llm/model';
3
  import { MAX_TOKENS } from './constants';
4
- import { getSystemPrompt } from './prompts';
5
- import { DEFAULT_MODEL, DEFAULT_PROVIDER, getModelList, MODEL_REGEX, PROVIDER_REGEX } from '~/utils/constants';
 
 
 
 
 
 
 
 
6
  import ignore from 'ignore';
7
  import type { IProviderSetting } from '~/types/model';
 
 
8
 
9
  interface ToolResult<Name extends string, Args, Result> {
10
  toolCallId: string;
@@ -139,8 +149,9 @@ export async function streamText(props: {
139
  apiKeys?: Record<string, string>;
140
  files?: FileMap;
141
  providerSettings?: Record<string, IProviderSetting>;
 
142
  }) {
143
- const { messages, env, options, apiKeys, files, providerSettings } = props;
144
  let currentModel = DEFAULT_MODEL;
145
  let currentProvider = DEFAULT_PROVIDER.name;
146
  const MODEL_LIST = await getModelList(apiKeys || {}, providerSettings);
@@ -170,11 +181,17 @@ export async function streamText(props: {
170
 
171
  const dynamicMaxTokens = modelDetails && modelDetails.maxTokenAllowed ? modelDetails.maxTokenAllowed : MAX_TOKENS;
172
 
173
- let systemPrompt = getSystemPrompt();
 
 
 
 
 
174
  let codeContext = '';
175
 
176
  if (files) {
177
  codeContext = createFilesContext(files);
 
178
  systemPrompt = `${systemPrompt}\n\n ${codeContext}`;
179
  }
180
 
 
1
  import { convertToCoreMessages, streamText as _streamText } from 'ai';
2
  import { getModel } from '~/lib/.server/llm/model';
3
  import { MAX_TOKENS } from './constants';
4
+ import { getSystemPrompt } from '~/lib/common/prompts/prompts';
5
+ import {
6
+ DEFAULT_MODEL,
7
+ DEFAULT_PROVIDER,
8
+ getModelList,
9
+ MODEL_REGEX,
10
+ MODIFICATIONS_TAG_NAME,
11
+ PROVIDER_REGEX,
12
+ WORK_DIR,
13
+ } from '~/utils/constants';
14
  import ignore from 'ignore';
15
  import type { IProviderSetting } from '~/types/model';
16
+ import { PromptLibrary } from '~/lib/common/prompt-library';
17
+ import { allowedHTMLElements } from '~/utils/markdown';
18
 
19
  interface ToolResult<Name extends string, Args, Result> {
20
  toolCallId: string;
 
149
  apiKeys?: Record<string, string>;
150
  files?: FileMap;
151
  providerSettings?: Record<string, IProviderSetting>;
152
+ promptId?: string;
153
  }) {
154
+ const { messages, env, options, apiKeys, files, providerSettings, promptId } = props;
155
  let currentModel = DEFAULT_MODEL;
156
  let currentProvider = DEFAULT_PROVIDER.name;
157
  const MODEL_LIST = await getModelList(apiKeys || {}, providerSettings);
 
181
 
182
  const dynamicMaxTokens = modelDetails && modelDetails.maxTokenAllowed ? modelDetails.maxTokenAllowed : MAX_TOKENS;
183
 
184
+ let systemPrompt =
185
+ PromptLibrary.getPropmtFromLibrary(promptId || 'default', {
186
+ cwd: WORK_DIR,
187
+ allowedHtmlElements: allowedHTMLElements,
188
+ modificationTagName: MODIFICATIONS_TAG_NAME,
189
+ }) ?? getSystemPrompt();
190
  let codeContext = '';
191
 
192
  if (files) {
193
  codeContext = createFilesContext(files);
194
+ codeContext = '';
195
  systemPrompt = `${systemPrompt}\n\n ${codeContext}`;
196
  }
197
 
app/lib/common/prompt-library.ts ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { getSystemPrompt } from './prompts/prompts';
2
+ import optimized from './prompts/optimized';
3
+
4
+ export interface PromptOptions {
5
+ cwd: string;
6
+ allowedHtmlElements: string[];
7
+ modificationTagName: string;
8
+ }
9
+
10
+ export class PromptLibrary {
11
+ static library: Record<
12
+ string,
13
+ {
14
+ label: string;
15
+ description: string;
16
+ get: (options: PromptOptions) => string;
17
+ }
18
+ > = {
19
+ default: {
20
+ label: 'Default Prompt',
21
+ description: 'This is the battle tested default system Prompt',
22
+ get: (options) => getSystemPrompt(options.cwd),
23
+ },
24
+ optimized: {
25
+ label: 'Optimized Prompt (experimental)',
26
+ description: 'an Experimental version of the prompt for lower token usage',
27
+ get: (options) => optimized(options),
28
+ },
29
+ };
30
+ static getList() {
31
+ return Object.entries(this.library).map(([key, value]) => {
32
+ const { label, description } = value;
33
+ return {
34
+ id: key,
35
+ label,
36
+ description,
37
+ };
38
+ });
39
+ }
40
+ static getPropmtFromLibrary(promptId: string, options: PromptOptions) {
41
+ const prompt = this.library[promptId];
42
+
43
+ if (!prompt) {
44
+ throw 'Prompt Now Found';
45
+ }
46
+
47
+ return this.library[promptId]?.get(options);
48
+ }
49
+ }
app/lib/common/prompts/optimized.ts ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { PromptOptions } from '~/lib/common/prompt-library';
2
+
3
+ export default (options: PromptOptions) => {
4
+ const { cwd, allowedHtmlElements, modificationTagName } = options;
5
+ return `
6
+ You are Bolt, an expert AI assistant and exceptional senior software developer with vast knowledge across multiple programming languages, frameworks, and best practices.
7
+
8
+ <system_constraints>
9
+ - Operating in WebContainer, an in-browser Node.js runtime
10
+ - Limited Python support: standard library only, no pip
11
+ - No C/C++ compiler, native binaries, or Git
12
+ - Prefer Node.js scripts over shell scripts
13
+ - Use Vite for web servers
14
+ - Databases: prefer libsql, sqlite, or non-native solutions
15
+ - When for react dont forget to write vite config and index.html to the project
16
+
17
+ Available shell commands: cat, cp, ls, mkdir, mv, rm, rmdir, touch, hostname, ps, pwd, uptime, env, node, python3, code, jq, curl, head, sort, tail, clear, which, export, chmod, scho, kill, ln, xxd, alias, getconf, loadenv, wasm, xdg-open, command, exit, source
18
+ </system_constraints>
19
+
20
+ <code_formatting_info>
21
+ Use 2 spaces for indentation
22
+ </code_formatting_info>
23
+
24
+ <message_formatting_info>
25
+ Available HTML elements: ${allowedHtmlElements.join(', ')}
26
+ </message_formatting_info>
27
+
28
+ <diff_spec>
29
+ File modifications in \`<${modificationTagName}>\` section:
30
+ - \`<diff path="/path/to/file">\`: GNU unified diff format
31
+ - \`<file path="/path/to/file">\`: Full new content
32
+ </diff_spec>
33
+
34
+ <chain_of_thought_instructions>
35
+ do not mention the phrase "chain of thought"
36
+ Before solutions, briefly outline implementation steps (2-4 lines max):
37
+ - List concrete steps
38
+ - Identify key components
39
+ - Note potential challenges
40
+ - Do not write the actual code just the plan and structure if needed
41
+ - Once completed planning start writing the artifacts
42
+ </chain_of_thought_instructions>
43
+
44
+ <artifact_info>
45
+ Create a single, comprehensive artifact for each project:
46
+ - Use \`<boltArtifact>\` tags with \`title\` and \`id\` attributes
47
+ - Use \`<boltAction>\` tags with \`type\` attribute:
48
+ - shell: Run commands
49
+ - file: Write/update files (use \`filePath\` attribute)
50
+ - start: Start dev server (only when necessary)
51
+ - Order actions logically
52
+ - Install dependencies first
53
+ - Provide full, updated content for all files
54
+ - Use coding best practices: modular, clean, readable code
55
+ </artifact_info>
56
+
57
+
58
+ # CRITICAL RULES - NEVER IGNORE
59
+
60
+ ## File and Command Handling
61
+ 1. ALWAYS use artifacts for file contents and commands - NO EXCEPTIONS
62
+ 2. When writing a file, INCLUDE THE ENTIRE FILE CONTENT - NO PARTIAL UPDATES
63
+ 3. For modifications, ONLY alter files that require changes - DO NOT touch unaffected files
64
+
65
+ ## Response Format
66
+ 4. Use markdown EXCLUSIVELY - HTML tags are ONLY allowed within artifacts
67
+ 5. Be concise - Explain ONLY when explicitly requested
68
+ 6. NEVER use the word "artifact" in responses
69
+
70
+ ## Development Process
71
+ 7. ALWAYS think and plan comprehensively before providing a solution
72
+ 8. Current working directory: \`${cwd} \` - Use this for all file paths
73
+ 9. Don't use cli scaffolding to steup the project, use cwd as Root of the project
74
+ 11. For nodejs projects ALWAYS install dependencies after writing package.json file
75
+
76
+ ## Coding Standards
77
+ 10. ALWAYS create smaller, atomic components and modules
78
+ 11. Modularity is PARAMOUNT - Break down functionality into logical, reusable parts
79
+ 12. IMMEDIATELY refactor any file exceeding 250 lines
80
+ 13. ALWAYS plan refactoring before implementation - Consider impacts on the entire system
81
+
82
+ ## Artifact Usage
83
+ 22. Use \`<boltArtifact>\` tags with \`title\` and \`id\` attributes for each project
84
+ 23. Use \`<boltAction>\` tags with appropriate \`type\` attribute:
85
+ - \`shell\`: For running commands
86
+ - \`file\`: For writing/updating files (include \`filePath\` attribute)
87
+ - \`start\`: For starting dev servers (use only when necessary/ or new dependencies are installed)
88
+ 24. Order actions logically - dependencies MUST be installed first
89
+ 25. For Vite project must include vite config and index.html for entry point
90
+ 26. Provide COMPLETE, up-to-date content for all files - NO placeholders or partial updates
91
+
92
+ CRITICAL: These rules are ABSOLUTE and MUST be followed WITHOUT EXCEPTION in EVERY response.
93
+
94
+ Examples:
95
+ <examples>
96
+ <example>
97
+ <user_query>Can you help me create a JavaScript function to calculate the factorial of a number?</user_query>
98
+ <assistant_response>
99
+ Certainly, I can help you create a JavaScript function to calculate the factorial of a number.
100
+
101
+ <boltArtifact id="factorial-function" title="JavaScript Factorial Function">
102
+ <boltAction type="file" filePath="index.js">
103
+ function factorial(n) {
104
+ ...
105
+ }
106
+
107
+ ...
108
+ </boltAction>
109
+ <boltAction type="shell">
110
+ node index.js
111
+ </boltAction>
112
+ </boltArtifact>
113
+ </assistant_response>
114
+ </example>
115
+
116
+ <example>
117
+ <user_query>Build a snake game</user_query>
118
+ <assistant_response>
119
+ Certainly! I'd be happy to help you build a snake game using JavaScript and HTML5 Canvas. This will be a basic implementation that you can later expand upon. Let's create the game step by step.
120
+
121
+ <boltArtifact id="snake-game" title="Snake Game in HTML and JavaScript">
122
+ <boltAction type="file" filePath="package.json">
123
+ {
124
+ "name": "snake",
125
+ "scripts": {
126
+ "dev": "vite"
127
+ }
128
+ ...
129
+ }
130
+ </boltAction>
131
+ <boltAction type="shell">
132
+ npm install --save-dev vite
133
+ </boltAction>
134
+ <boltAction type="file" filePath="index.html">
135
+ ...
136
+ </boltAction>
137
+ <boltAction type="start">
138
+ npm run dev
139
+ </boltAction>
140
+ </boltArtifact>
141
+
142
+ Now you can play the Snake game by opening the provided local server URL in your browser. Use the arrow keys to control the snake. Eat the red food to grow and increase your score. The game ends if you hit the wall or your own tail.
143
+ </assistant_response>
144
+ </example>
145
+
146
+ <example>
147
+ <user_query>Make a bouncing ball with real gravity using React</user_query>
148
+ <assistant_response>
149
+ Certainly! I'll create a bouncing ball with real gravity using React. We'll use the react-spring library for physics-based animations.
150
+
151
+ <boltArtifact id="bouncing-ball-react" title="Bouncing Ball with Gravity in React">
152
+ <boltAction type="file" filePath="package.json">
153
+ {
154
+ "name": "bouncing-ball",
155
+ "private": true,
156
+ "version": "0.0.0",
157
+ "type": "module",
158
+ "scripts": {
159
+ "dev": "vite",
160
+ "build": "vite build",
161
+ "preview": "vite preview"
162
+ },
163
+ "dependencies": {
164
+ "react": "^18.2.0",
165
+ "react-dom": "^18.2.0",
166
+ "react-spring": "^9.7.1"
167
+ },
168
+ "devDependencies": {
169
+ "@types/react": "^18.0.28",
170
+ "@types/react-dom": "^18.0.11",
171
+ "@vitejs/plugin-react": "^3.1.0",
172
+ "vite": "^4.2.0"
173
+ }
174
+ }
175
+ </boltAction>
176
+ <boltAction type="file" filePath="index.html">
177
+ ...
178
+ </boltAction>
179
+ <boltAction type="file" filePath="src/main.jsx">
180
+ ...
181
+ </boltAction>
182
+ <boltAction type="file" filePath="src/index.css">
183
+ ...
184
+ </boltAction>
185
+ <boltAction type="file" filePath="src/App.jsx">
186
+ ...
187
+ </boltAction>
188
+ <boltAction type="start">
189
+ npm run dev
190
+ </boltAction>
191
+ </boltArtifact>
192
+
193
+ You can now view the bouncing ball animation in the preview. The ball will start falling from the top of the screen and bounce realistically when it hits the bottom.
194
+ </assistant_response>
195
+ </example>
196
+ </examples>
197
+ Always use artifacts for file contents and commands, following the format shown in these examples.
198
+ `;
199
+ };
app/lib/{.server/llm β†’ common/prompts}/prompts.ts RENAMED
File without changes
app/lib/hooks/useSettings.tsx CHANGED
@@ -4,6 +4,7 @@ import {
4
  isEventLogsEnabled,
5
  isLocalModelsEnabled,
6
  LOCAL_PROVIDERS,
 
7
  providersStore,
8
  latestBranchStore,
9
  } from '~/lib/stores/settings';
@@ -24,8 +25,9 @@ export function useSettings() {
24
  const providers = useStore(providersStore);
25
  const debug = useStore(isDebugMode);
26
  const eventLogs = useStore(isEventLogsEnabled);
 
27
  const isLocalModel = useStore(isLocalModelsEnabled);
28
- const latestBranch = useStore(latestBranchStore);
29
  const [activeProviders, setActiveProviders] = useState<ProviderInfo[]>([]);
30
 
31
  // Function to check if we're on stable version
@@ -92,8 +94,14 @@ export function useSettings() {
92
  isLocalModelsEnabled.set(savedLocalModels === 'true');
93
  }
94
 
 
 
 
 
 
 
95
  // load latest branch setting from cookies or determine based on version
96
- const savedLatestBranch = Cookies.get('latestBranch');
97
  let checkCommit = Cookies.get('commitHash');
98
 
99
  if (checkCommit === undefined) {
@@ -105,7 +113,7 @@ export function useSettings() {
105
  checkIsStableVersion().then((isStable) => {
106
  const shouldUseLatest = !isStable;
107
  latestBranchStore.set(shouldUseLatest);
108
- Cookies.set('latestBranch', String(shouldUseLatest));
109
  Cookies.set('commitHash', String(commit.commit));
110
  });
111
  } else {
@@ -162,10 +170,14 @@ export function useSettings() {
162
  Cookies.set('isLocalModelsEnabled', String(enabled));
163
  }, []);
164
 
 
 
 
 
165
  const enableLatestBranch = useCallback((enabled: boolean) => {
166
  latestBranchStore.set(enabled);
167
  logStore.logSystem(`Main branch updates ${enabled ? 'enabled' : 'disabled'}`);
168
- Cookies.set('latestBranch', String(enabled));
169
  }, []);
170
 
171
  return {
@@ -178,7 +190,9 @@ export function useSettings() {
178
  enableEventLogs,
179
  isLocalModel,
180
  enableLocalModels,
181
- latestBranch,
 
 
182
  enableLatestBranch,
183
  };
184
  }
 
4
  isEventLogsEnabled,
5
  isLocalModelsEnabled,
6
  LOCAL_PROVIDERS,
7
+ promptStore,
8
  providersStore,
9
  latestBranchStore,
10
  } from '~/lib/stores/settings';
 
25
  const providers = useStore(providersStore);
26
  const debug = useStore(isDebugMode);
27
  const eventLogs = useStore(isEventLogsEnabled);
28
+ const promptId = useStore(promptStore);
29
  const isLocalModel = useStore(isLocalModelsEnabled);
30
+ const isLatestBranch = useStore(latestBranchStore);
31
  const [activeProviders, setActiveProviders] = useState<ProviderInfo[]>([]);
32
 
33
  // Function to check if we're on stable version
 
94
  isLocalModelsEnabled.set(savedLocalModels === 'true');
95
  }
96
 
97
+ const promptId = Cookies.get('promptId');
98
+
99
+ if (promptId) {
100
+ promptStore.set(promptId);
101
+ }
102
+
103
  // load latest branch setting from cookies or determine based on version
104
+ const savedLatestBranch = Cookies.get('isLatestBranch');
105
  let checkCommit = Cookies.get('commitHash');
106
 
107
  if (checkCommit === undefined) {
 
113
  checkIsStableVersion().then((isStable) => {
114
  const shouldUseLatest = !isStable;
115
  latestBranchStore.set(shouldUseLatest);
116
+ Cookies.set('isLatestBranch', String(shouldUseLatest));
117
  Cookies.set('commitHash', String(commit.commit));
118
  });
119
  } else {
 
170
  Cookies.set('isLocalModelsEnabled', String(enabled));
171
  }, []);
172
 
173
+ const setPromptId = useCallback((promptId: string) => {
174
+ promptStore.set(promptId);
175
+ Cookies.set('promptId', promptId);
176
+ }, []);
177
  const enableLatestBranch = useCallback((enabled: boolean) => {
178
  latestBranchStore.set(enabled);
179
  logStore.logSystem(`Main branch updates ${enabled ? 'enabled' : 'disabled'}`);
180
+ Cookies.set('isLatestBranch', String(enabled));
181
  }, []);
182
 
183
  return {
 
190
  enableEventLogs,
191
  isLocalModel,
192
  enableLocalModels,
193
+ promptId,
194
+ setPromptId,
195
+ isLatestBranch,
196
  enableLatestBranch,
197
  };
198
  }
app/lib/stores/settings.ts CHANGED
@@ -47,4 +47,6 @@ export const isEventLogsEnabled = atom(false);
47
 
48
  export const isLocalModelsEnabled = atom(true);
49
 
 
 
50
  export const latestBranchStore = atom(false);
 
47
 
48
  export const isLocalModelsEnabled = atom(true);
49
 
50
+ export const promptStore = atom<string>('default');
51
+
52
  export const latestBranchStore = atom(false);
app/routes/api.chat.ts CHANGED
@@ -1,7 +1,7 @@
1
  import { type ActionFunctionArgs } from '@remix-run/cloudflare';
2
  import { createDataStream } from 'ai';
3
  import { MAX_RESPONSE_SEGMENTS, MAX_TOKENS } from '~/lib/.server/llm/constants';
4
- import { CONTINUE_PROMPT } from '~/lib/.server/llm/prompts';
5
  import { streamText, type Messages, type StreamingOptions } from '~/lib/.server/llm/stream-text';
6
  import SwitchableStream from '~/lib/.server/llm/switchable-stream';
7
  import type { IProviderSetting } from '~/types/model';
@@ -29,9 +29,10 @@ function parseCookies(cookieHeader: string): Record<string, string> {
29
  }
30
 
31
  async function chatAction({ context, request }: ActionFunctionArgs) {
32
- const { messages, files } = await request.json<{
33
  messages: Messages;
34
  files: any;
 
35
  }>();
36
 
37
  const cookieHeader = request.headers.get('Cookie');
@@ -98,6 +99,7 @@ async function chatAction({ context, request }: ActionFunctionArgs) {
98
  apiKeys,
99
  files,
100
  providerSettings,
 
101
  });
102
 
103
  return stream.switchSource(result.toDataStream());
@@ -111,6 +113,7 @@ async function chatAction({ context, request }: ActionFunctionArgs) {
111
  apiKeys,
112
  files,
113
  providerSettings,
 
114
  });
115
 
116
  stream.switchSource(result.toDataStream());
 
1
  import { type ActionFunctionArgs } from '@remix-run/cloudflare';
2
  import { createDataStream } from 'ai';
3
  import { MAX_RESPONSE_SEGMENTS, MAX_TOKENS } from '~/lib/.server/llm/constants';
4
+ import { CONTINUE_PROMPT } from '~/lib/common/prompts/prompts';
5
  import { streamText, type Messages, type StreamingOptions } from '~/lib/.server/llm/stream-text';
6
  import SwitchableStream from '~/lib/.server/llm/switchable-stream';
7
  import type { IProviderSetting } from '~/types/model';
 
29
  }
30
 
31
  async function chatAction({ context, request }: ActionFunctionArgs) {
32
+ const { messages, files, promptId } = await request.json<{
33
  messages: Messages;
34
  files: any;
35
+ promptId?: string;
36
  }>();
37
 
38
  const cookieHeader = request.headers.get('Cookie');
 
99
  apiKeys,
100
  files,
101
  providerSettings,
102
+ promptId,
103
  });
104
 
105
  return stream.switchSource(result.toDataStream());
 
113
  apiKeys,
114
  files,
115
  providerSettings,
116
+ promptId,
117
  });
118
 
119
  stream.switchSource(result.toDataStream());