feat: Experimental Prompt Library Added
Browse files- app/commit.json +1 -1
- app/components/chat/Chat.client.tsx +2 -1
- app/components/settings/features/FeaturesTab.tsx +23 -4
- app/lib/.server/llm/stream-text.ts +21 -4
- app/lib/common/prompt-library.ts +49 -0
- app/lib/common/prompts/optimized.ts +135 -0
- app/lib/{.server/llm → common/prompts}/prompts.ts +0 -0
- app/lib/hooks/useSettings.tsx +15 -0
- app/lib/stores/settings.ts +2 -0
- app/lib/stores/workbench.ts +0 -1
- app/routes/api.chat.ts +5 -2
app/commit.json
CHANGED
@@ -1 +1 @@
|
|
1 |
-
{ "commit": "
|
|
|
1 |
+
{ "commit": "79ce87ee5d729185bad73a37ebf77964f1488f59" }
|
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 |
onError: (error) => {
|
120 |
logger.error('Request failed\n\n', 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 |
onError: (error) => {
|
121 |
logger.error('Request failed\n\n', error);
|
app/components/settings/features/FeaturesTab.tsx
CHANGED
@@ -1,18 +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, eventLogs, enableEventLogs } =
|
|
|
7 |
return (
|
8 |
<div className="p-4 bg-bolt-elements-bg-depth-2 border border-bolt-elements-borderColor rounded-lg mb-4">
|
9 |
<div className="mb-6">
|
10 |
<h3 className="text-lg font-medium text-bolt-elements-textPrimary mb-4">Optional Features</h3>
|
11 |
-
<div className="flex items-center justify-between mb-
|
12 |
<span className="text-bolt-elements-textPrimary">Debug Info</span>
|
13 |
<Switch className="ml-auto" checked={debug} onCheckedChange={enableDebugMode} />
|
14 |
</div>
|
15 |
-
<div className="flex items-center justify-between mb-
|
16 |
<span className="text-bolt-elements-textPrimary">Event Logs</span>
|
17 |
<Switch className="ml-auto" checked={eventLogs} onCheckedChange={enableEventLogs} />
|
18 |
</div>
|
@@ -23,10 +25,27 @@ export default function FeaturesTab() {
|
|
23 |
<p className="text-sm text-bolt-elements-textSecondary mb-4">
|
24 |
Disclaimer: Experimental features may be unstable and are subject to change.
|
25 |
</p>
|
26 |
-
<div className="flex items-center justify-between mb-
|
27 |
<span className="text-bolt-elements-textPrimary">Enable Local Models</span>
|
28 |
<Switch className="ml-auto" checked={isLocalModel} onCheckedChange={enableLocalModels} />
|
29 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
</div>
|
31 |
</div>
|
32 |
);
|
|
|
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 { debug, enableDebugMode, isLocalModel, enableLocalModels, eventLogs, enableEventLogs, promptId, setPromptId } =
|
8 |
+
useSettings();
|
9 |
return (
|
10 |
<div className="p-4 bg-bolt-elements-bg-depth-2 border border-bolt-elements-borderColor rounded-lg mb-4">
|
11 |
<div className="mb-6">
|
12 |
<h3 className="text-lg font-medium text-bolt-elements-textPrimary mb-4">Optional Features</h3>
|
13 |
+
<div className="flex items-center justify-between mb-6">
|
14 |
<span className="text-bolt-elements-textPrimary">Debug Info</span>
|
15 |
<Switch className="ml-auto" checked={debug} onCheckedChange={enableDebugMode} />
|
16 |
</div>
|
17 |
+
<div className="flex items-center justify-between mb-6">
|
18 |
<span className="text-bolt-elements-textPrimary">Event Logs</span>
|
19 |
<Switch className="ml-auto" checked={eventLogs} onCheckedChange={enableEventLogs} />
|
20 |
</div>
|
|
|
25 |
<p className="text-sm text-bolt-elements-textSecondary mb-4">
|
26 |
Disclaimer: Experimental features may be unstable and are subject to change.
|
27 |
</p>
|
28 |
+
<div className="flex items-center justify-between pt-4 mb-4">
|
29 |
<span className="text-bolt-elements-textPrimary">Enable Local Models</span>
|
30 |
<Switch className="ml-auto" checked={isLocalModel} onCheckedChange={enableLocalModels} />
|
31 |
</div>
|
32 |
+
<div className="flex items-start justify-between pt-4 mb-2 gap-2">
|
33 |
+
<div className="flex-1 max-w-[200px]">
|
34 |
+
<span className="text-bolt-elements-textPrimary">Prompt Library</span>
|
35 |
+
<p className="text-sm text-bolt-elements-textSecondary mb-4">
|
36 |
+
Choose a prompt from the library to use as the system prompt.
|
37 |
+
</p>
|
38 |
+
</div>
|
39 |
+
<select
|
40 |
+
value={promptId}
|
41 |
+
onChange={(e) => setPromptId(e.target.value)}
|
42 |
+
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]"
|
43 |
+
>
|
44 |
+
{PromptLibrary.getList().map((x) => (
|
45 |
+
<option value={x.id}>{x.label}</option>
|
46 |
+
))}
|
47 |
+
</select>
|
48 |
+
</div>
|
49 |
</div>
|
50 |
</div>
|
51 |
);
|
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 '
|
5 |
-
import {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 =
|
|
|
|
|
|
|
|
|
|
|
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,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 senior software developer.
|
7 |
+
You have access to a shell and access to write files through the use of artifacts.
|
8 |
+
Your artifacts will be parsed by automated parser to perform actions on your behalf and will not be visible to the user
|
9 |
+
|
10 |
+
<system_constraints>
|
11 |
+
- Operating in WebContainer, an in-browser Node.js runtime
|
12 |
+
- Limited Python support: standard library only, no pip
|
13 |
+
- No C/C++ compiler, native binaries, or Git
|
14 |
+
- Prefer Node.js scripts over shell scripts
|
15 |
+
- Use Vite for web servers
|
16 |
+
- Databases: prefer libsql, sqlite, or non-native solutions
|
17 |
+
- When for react dont forget to write vite config and index.html to the project
|
18 |
+
|
19 |
+
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
|
20 |
+
</system_constraints>
|
21 |
+
|
22 |
+
<code_formatting_info>
|
23 |
+
Use 2 spaces for indentation
|
24 |
+
</code_formatting_info>
|
25 |
+
|
26 |
+
<message_formatting_info>
|
27 |
+
Available HTML elements: ${allowedHtmlElements.join(', ')}
|
28 |
+
</message_formatting_info>
|
29 |
+
|
30 |
+
<diff_spec>
|
31 |
+
File modifications in \`<${modificationTagName}>\` section:
|
32 |
+
- \`<diff path="/path/to/file">\`: GNU unified diff format
|
33 |
+
- \`<file path="/path/to/file">\`: Full new content
|
34 |
+
</diff_spec>
|
35 |
+
|
36 |
+
<chain_of_thought_instructions>
|
37 |
+
do not mention the phrase "chain of thought"
|
38 |
+
Before solutions, briefly outline implementation steps (2-4 lines max):
|
39 |
+
- List concrete steps
|
40 |
+
- Identify key components
|
41 |
+
- Note potential challenges
|
42 |
+
- Do not write the actual code just the plan and structure if needed
|
43 |
+
- Once completed planning start writing the artifacts
|
44 |
+
</chain_of_thought_instructions>
|
45 |
+
|
46 |
+
<artifact_info>
|
47 |
+
Create a single, comprehensive artifact for each project:
|
48 |
+
- Use \`<boltArtifact>\` tags with \`title\` and \`id\` attributes
|
49 |
+
- Use \`<boltAction>\` tags with \`type\` attribute:
|
50 |
+
- shell: Run commands
|
51 |
+
- file: Write/update files (use \`filePath\` attribute)
|
52 |
+
- start: Start dev server (only when necessary)
|
53 |
+
- Order actions logically
|
54 |
+
- Install dependencies first
|
55 |
+
- Provide full, updated content for all files
|
56 |
+
- Use coding best practices: modular, clean, readable code
|
57 |
+
</artifact_info>
|
58 |
+
|
59 |
+
Key points:
|
60 |
+
- Always use artifacts for file contents and commands
|
61 |
+
- Use markdown, avoid HTML tags except in artifacts
|
62 |
+
- Be concise, explain only when asked
|
63 |
+
- Think first, then provide comprehensive artifact
|
64 |
+
- Never use the word "artifact" in responses
|
65 |
+
- Current working directory: \`${cwd}\`
|
66 |
+
|
67 |
+
Examples:
|
68 |
+
|
69 |
+
<examples>
|
70 |
+
<example>
|
71 |
+
<user_query>Create a JavaScript factorial function</user_query>
|
72 |
+
<assistant_response>
|
73 |
+
Certainly, I'll create a JavaScript factorial function for you.
|
74 |
+
|
75 |
+
<boltArtifact id="factorial-function" title="JavaScript Factorial Function">
|
76 |
+
<boltAction type="file" filePath="factorial.js">
|
77 |
+
function factorial(n) {
|
78 |
+
return n <= 1 ? 1 : n * factorial(n - 1);
|
79 |
+
}
|
80 |
+
console.log(factorial(5));
|
81 |
+
</boltAction>
|
82 |
+
<boltAction type="shell">
|
83 |
+
node factorial.js
|
84 |
+
</boltAction>
|
85 |
+
</boltArtifact>
|
86 |
+
|
87 |
+
This creates a factorial function and tests it with the value 5.
|
88 |
+
</assistant_response>
|
89 |
+
</example>
|
90 |
+
|
91 |
+
<example>
|
92 |
+
<user_query>Set up a basic React project</user_query>
|
93 |
+
<assistant_response>
|
94 |
+
Sure, I'll set up a basic React project for you.
|
95 |
+
|
96 |
+
<boltArtifact id="react-setup" title="Basic React Project Setup">
|
97 |
+
<boltAction type="file" filePath="package.json">
|
98 |
+
{
|
99 |
+
"name": "react-project",
|
100 |
+
"version": "1.0.0",
|
101 |
+
"scripts": {
|
102 |
+
"dev": "vite"
|
103 |
+
},
|
104 |
+
"dependencies": {
|
105 |
+
"react": "^18.2.0",
|
106 |
+
"react-dom": "^18.2.0"
|
107 |
+
},
|
108 |
+
"devDependencies": {
|
109 |
+
"vite": "^4.3.9"
|
110 |
+
}
|
111 |
+
}
|
112 |
+
</boltAction>
|
113 |
+
<boltAction type="shell">
|
114 |
+
npm install
|
115 |
+
</boltAction>
|
116 |
+
<boltAction type="file" filePath="src/App.jsx">
|
117 |
+
import React from 'react';
|
118 |
+
function App() {
|
119 |
+
return <h1>Hello, React!</h1>;
|
120 |
+
}
|
121 |
+
export default App;
|
122 |
+
</boltAction>
|
123 |
+
<boltAction type="start">
|
124 |
+
npm run dev
|
125 |
+
</boltAction>
|
126 |
+
</boltArtifact>
|
127 |
+
|
128 |
+
This sets up a basic React project with Vite as the build tool.
|
129 |
+
</assistant_response>
|
130 |
+
</example>
|
131 |
+
</examples>
|
132 |
+
|
133 |
+
Always use artifacts for file contents and commands, following the format shown in these examples.
|
134 |
+
`;
|
135 |
+
};
|
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 |
} from '~/lib/stores/settings';
|
9 |
import { useCallback, useEffect, useState } from 'react';
|
@@ -15,6 +16,7 @@ export function useSettings() {
|
|
15 |
const providers = useStore(providersStore);
|
16 |
const debug = useStore(isDebugMode);
|
17 |
const eventLogs = useStore(isEventLogsEnabled);
|
|
|
18 |
const isLocalModel = useStore(isLocalModelsEnabled);
|
19 |
const [activeProviders, setActiveProviders] = useState<ProviderInfo[]>([]);
|
20 |
|
@@ -60,6 +62,12 @@ export function useSettings() {
|
|
60 |
if (savedLocalModels) {
|
61 |
isLocalModelsEnabled.set(savedLocalModels === 'true');
|
62 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
}, []);
|
64 |
|
65 |
// writing values to cookies on change
|
@@ -111,6 +119,11 @@ export function useSettings() {
|
|
111 |
Cookies.set('isLocalModelsEnabled', String(enabled));
|
112 |
}, []);
|
113 |
|
|
|
|
|
|
|
|
|
|
|
114 |
return {
|
115 |
providers,
|
116 |
activeProviders,
|
@@ -121,5 +134,7 @@ export function useSettings() {
|
|
121 |
enableEventLogs,
|
122 |
isLocalModel,
|
123 |
enableLocalModels,
|
|
|
|
|
124 |
};
|
125 |
}
|
|
|
4 |
isEventLogsEnabled,
|
5 |
isLocalModelsEnabled,
|
6 |
LOCAL_PROVIDERS,
|
7 |
+
promptStore,
|
8 |
providersStore,
|
9 |
} from '~/lib/stores/settings';
|
10 |
import { useCallback, useEffect, useState } from 'react';
|
|
|
16 |
const providers = useStore(providersStore);
|
17 |
const debug = useStore(isDebugMode);
|
18 |
const eventLogs = useStore(isEventLogsEnabled);
|
19 |
+
const promptId = useStore(promptStore);
|
20 |
const isLocalModel = useStore(isLocalModelsEnabled);
|
21 |
const [activeProviders, setActiveProviders] = useState<ProviderInfo[]>([]);
|
22 |
|
|
|
62 |
if (savedLocalModels) {
|
63 |
isLocalModelsEnabled.set(savedLocalModels === 'true');
|
64 |
}
|
65 |
+
|
66 |
+
const promptId = Cookies.get('promptId');
|
67 |
+
|
68 |
+
if (promptId) {
|
69 |
+
promptStore.set(promptId);
|
70 |
+
}
|
71 |
}, []);
|
72 |
|
73 |
// writing values to cookies on change
|
|
|
119 |
Cookies.set('isLocalModelsEnabled', String(enabled));
|
120 |
}, []);
|
121 |
|
122 |
+
const setPromptId = useCallback((promptId: string) => {
|
123 |
+
promptStore.set(promptId);
|
124 |
+
Cookies.set('promptId', promptId);
|
125 |
+
}, []);
|
126 |
+
|
127 |
return {
|
128 |
providers,
|
129 |
activeProviders,
|
|
|
134 |
enableEventLogs,
|
135 |
isLocalModel,
|
136 |
enableLocalModels,
|
137 |
+
promptId,
|
138 |
+
setPromptId,
|
139 |
};
|
140 |
}
|
app/lib/stores/settings.ts
CHANGED
@@ -46,3 +46,5 @@ export const isDebugMode = atom(false);
|
|
46 |
export const isEventLogsEnabled = atom(false);
|
47 |
|
48 |
export const isLocalModelsEnabled = atom(true);
|
|
|
|
|
|
46 |
export const isEventLogsEnabled = atom(false);
|
47 |
|
48 |
export const isLocalModelsEnabled = atom(true);
|
49 |
+
|
50 |
+
export const promptStore = atom<string>('default');
|
app/lib/stores/workbench.ts
CHANGED
@@ -297,7 +297,6 @@ export class WorkbenchStore {
|
|
297 |
|
298 |
const action = artifact.runner.actions.get()[data.actionId];
|
299 |
|
300 |
-
|
301 |
if (!action || action.executed) {
|
302 |
return;
|
303 |
}
|
|
|
297 |
|
298 |
const action = artifact.runner.actions.get()[data.actionId];
|
299 |
|
|
|
300 |
if (!action || action.executed) {
|
301 |
return;
|
302 |
}
|
app/routes/api.chat.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
import { type ActionFunctionArgs } from '@remix-run/cloudflare';
|
2 |
import { MAX_RESPONSE_SEGMENTS, MAX_TOKENS } from '~/lib/.server/llm/constants';
|
3 |
-
import { CONTINUE_PROMPT } from '~/lib
|
4 |
import { streamText, type Messages, type StreamingOptions } from '~/lib/.server/llm/stream-text';
|
5 |
import SwitchableStream from '~/lib/.server/llm/switchable-stream';
|
6 |
import type { IProviderSetting } from '~/types/model';
|
@@ -30,9 +30,10 @@ function parseCookies(cookieHeader: string) {
|
|
30 |
}
|
31 |
|
32 |
async function chatAction({ context, request }: ActionFunctionArgs) {
|
33 |
-
const { messages, files } = await request.json<{
|
34 |
messages: Messages;
|
35 |
files: any;
|
|
|
36 |
}>();
|
37 |
|
38 |
const cookieHeader = request.headers.get('Cookie');
|
@@ -71,6 +72,7 @@ async function chatAction({ context, request }: ActionFunctionArgs) {
|
|
71 |
apiKeys,
|
72 |
files,
|
73 |
providerSettings,
|
|
|
74 |
});
|
75 |
|
76 |
return stream.switchSource(result.toAIStream());
|
@@ -84,6 +86,7 @@ async function chatAction({ context, request }: ActionFunctionArgs) {
|
|
84 |
apiKeys,
|
85 |
files,
|
86 |
providerSettings,
|
|
|
87 |
});
|
88 |
|
89 |
stream.switchSource(result.toAIStream());
|
|
|
1 |
import { type ActionFunctionArgs } from '@remix-run/cloudflare';
|
2 |
import { MAX_RESPONSE_SEGMENTS, MAX_TOKENS } from '~/lib/.server/llm/constants';
|
3 |
+
import { CONTINUE_PROMPT } from '~/lib/common/prompts/prompts';
|
4 |
import { streamText, type Messages, type StreamingOptions } from '~/lib/.server/llm/stream-text';
|
5 |
import SwitchableStream from '~/lib/.server/llm/switchable-stream';
|
6 |
import type { IProviderSetting } from '~/types/model';
|
|
|
30 |
}
|
31 |
|
32 |
async function chatAction({ context, request }: ActionFunctionArgs) {
|
33 |
+
const { messages, files, promptId } = await request.json<{
|
34 |
messages: Messages;
|
35 |
files: any;
|
36 |
+
promptId?: string;
|
37 |
}>();
|
38 |
|
39 |
const cookieHeader = request.headers.get('Cookie');
|
|
|
72 |
apiKeys,
|
73 |
files,
|
74 |
providerSettings,
|
75 |
+
promptId,
|
76 |
});
|
77 |
|
78 |
return stream.switchSource(result.toAIStream());
|
|
|
86 |
apiKeys,
|
87 |
files,
|
88 |
providerSettings,
|
89 |
+
promptId,
|
90 |
});
|
91 |
|
92 |
stream.switchSource(result.toAIStream());
|