feat: added Automatic Code Template Detection And Import (#867)
* initial setup * updated template list * added optional switch to control this feature * removed some logs
This commit is contained in:
@@ -22,6 +22,7 @@ import { useSettings } from '~/lib/hooks/useSettings';
|
||||
import type { ProviderInfo } from '~/types/model';
|
||||
import { useSearchParams } from '@remix-run/react';
|
||||
import { createSampler } from '~/utils/sampler';
|
||||
import { getTemplates, selectStarterTemplate } from '~/utils/selectStarterTemplate';
|
||||
|
||||
const toastAnimation = cssTransition({
|
||||
enter: 'animated fadeInRight',
|
||||
@@ -116,9 +117,10 @@ export const ChatImpl = memo(
|
||||
const [uploadedFiles, setUploadedFiles] = useState<File[]>([]); // Move here
|
||||
const [imageDataList, setImageDataList] = useState<string[]>([]); // Move here
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const [fakeLoading, setFakeLoading] = useState(false);
|
||||
const files = useStore(workbenchStore.files);
|
||||
const actionAlert = useStore(workbenchStore.alert);
|
||||
const { activeProviders, promptId, contextOptimizationEnabled } = useSettings();
|
||||
const { activeProviders, promptId, autoSelectTemplate, contextOptimizationEnabled } = useSettings();
|
||||
|
||||
const [model, setModel] = useState(() => {
|
||||
const savedModel = Cookies.get('selectedModel');
|
||||
@@ -135,7 +137,7 @@ export const ChatImpl = memo(
|
||||
|
||||
const [apiKeys, setApiKeys] = useState<Record<string, string>>({});
|
||||
|
||||
const { messages, isLoading, input, handleInputChange, setInput, stop, append } = useChat({
|
||||
const { messages, isLoading, input, handleInputChange, setInput, stop, append, setMessages, reload } = useChat({
|
||||
api: '/api/chat',
|
||||
body: {
|
||||
apiKeys,
|
||||
@@ -266,6 +268,110 @@ export const ChatImpl = memo(
|
||||
|
||||
runAnimation();
|
||||
|
||||
if (!chatStarted && messageInput && autoSelectTemplate) {
|
||||
setFakeLoading(true);
|
||||
setMessages([
|
||||
{
|
||||
id: `${new Date().getTime()}`,
|
||||
role: 'user',
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `[Model: ${model}]\n\n[Provider: ${provider.name}]\n\n${_input}`,
|
||||
},
|
||||
...imageDataList.map((imageData) => ({
|
||||
type: 'image',
|
||||
image: imageData,
|
||||
})),
|
||||
] as any, // Type assertion to bypass compiler check
|
||||
},
|
||||
]);
|
||||
|
||||
// reload();
|
||||
|
||||
const template = await selectStarterTemplate({
|
||||
message: messageInput,
|
||||
model,
|
||||
provider,
|
||||
});
|
||||
|
||||
if (template !== 'blank') {
|
||||
const temResp = await getTemplates(template);
|
||||
|
||||
if (temResp) {
|
||||
const { assistantMessage, userMessage } = temResp;
|
||||
|
||||
setMessages([
|
||||
{
|
||||
id: `${new Date().getTime()}`,
|
||||
role: 'user',
|
||||
content: messageInput,
|
||||
|
||||
// annotations: ['hidden'],
|
||||
},
|
||||
{
|
||||
id: `${new Date().getTime()}`,
|
||||
role: 'assistant',
|
||||
content: assistantMessage,
|
||||
},
|
||||
{
|
||||
id: `${new Date().getTime()}`,
|
||||
role: 'user',
|
||||
content: `[Model: ${model}]\n\n[Provider: ${provider.name}]\n\n${userMessage}`,
|
||||
annotations: ['hidden'],
|
||||
},
|
||||
]);
|
||||
|
||||
reload();
|
||||
setFakeLoading(false);
|
||||
|
||||
return;
|
||||
} else {
|
||||
setMessages([
|
||||
{
|
||||
id: `${new Date().getTime()}`,
|
||||
role: 'user',
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `[Model: ${model}]\n\n[Provider: ${provider.name}]\n\n${_input}`,
|
||||
},
|
||||
...imageDataList.map((imageData) => ({
|
||||
type: 'image',
|
||||
image: imageData,
|
||||
})),
|
||||
] as any, // Type assertion to bypass compiler check
|
||||
},
|
||||
]);
|
||||
reload();
|
||||
setFakeLoading(false);
|
||||
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
setMessages([
|
||||
{
|
||||
id: `${new Date().getTime()}`,
|
||||
role: 'user',
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `[Model: ${model}]\n\n[Provider: ${provider.name}]\n\n${_input}`,
|
||||
},
|
||||
...imageDataList.map((imageData) => ({
|
||||
type: 'image',
|
||||
image: imageData,
|
||||
})),
|
||||
] as any, // Type assertion to bypass compiler check
|
||||
},
|
||||
]);
|
||||
reload();
|
||||
setFakeLoading(false);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (fileModifications !== undefined) {
|
||||
/**
|
||||
* If we have file modifications we append a new user message manually since we have to prefix
|
||||
@@ -368,7 +474,7 @@ export const ChatImpl = memo(
|
||||
input={input}
|
||||
showChat={showChat}
|
||||
chatStarted={chatStarted}
|
||||
isStreaming={isLoading}
|
||||
isStreaming={isLoading || fakeLoading}
|
||||
enhancingPrompt={enhancingPrompt}
|
||||
promptEnhanced={promptEnhanced}
|
||||
sendMessage={sendMessage}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Message } from 'ai';
|
||||
import React from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import { classNames } from '~/utils/classNames';
|
||||
import { AssistantMessage } from './AssistantMessage';
|
||||
import { UserMessage } from './UserMessage';
|
||||
@@ -44,10 +44,15 @@ export const Messages = React.forwardRef<HTMLDivElement, MessagesProps>((props:
|
||||
<div id={id} ref={ref} className={props.className}>
|
||||
{messages.length > 0
|
||||
? messages.map((message, index) => {
|
||||
const { role, content, id: messageId } = message;
|
||||
const { role, content, id: messageId, annotations } = message;
|
||||
const isUserMessage = role === 'user';
|
||||
const isFirst = index === 0;
|
||||
const isLast = index === messages.length - 1;
|
||||
const isHidden = annotations?.includes('hidden');
|
||||
|
||||
if (isHidden) {
|
||||
return <Fragment key={index} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -14,6 +14,8 @@ export default function FeaturesTab() {
|
||||
enableLatestBranch,
|
||||
promptId,
|
||||
setPromptId,
|
||||
autoSelectTemplate,
|
||||
setAutoSelectTemplate,
|
||||
enableContextOptimization,
|
||||
contextOptimizationEnabled,
|
||||
} = useSettings();
|
||||
@@ -35,12 +37,21 @@ export default function FeaturesTab() {
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<span className="text-bolt-elements-textPrimary">Use Main Branch</span>
|
||||
<p className="text-sm text-bolt-elements-textSecondary">
|
||||
<p className="text-xs text-bolt-elements-textTertiary">
|
||||
Check for updates against the main branch instead of stable
|
||||
</p>
|
||||
</div>
|
||||
<Switch className="ml-auto" checked={isLatestBranch} onCheckedChange={enableLatestBranch} />
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<span className="text-bolt-elements-textPrimary">Auto Select Code Template</span>
|
||||
<p className="text-xs text-bolt-elements-textTertiary">
|
||||
Let Bolt select the best starter template for your project.
|
||||
</p>
|
||||
</div>
|
||||
<Switch className="ml-auto" checked={autoSelectTemplate} onCheckedChange={setAutoSelectTemplate} />
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<span className="text-bolt-elements-textPrimary">Use Context Optimization</span>
|
||||
@@ -59,18 +70,22 @@ export default function FeaturesTab() {
|
||||
|
||||
<div className="mb-6 border-t border-bolt-elements-borderColor pt-4">
|
||||
<h3 className="text-lg font-medium text-bolt-elements-textPrimary mb-4">Experimental Features</h3>
|
||||
<p className="text-sm text-bolt-elements-textSecondary mb-4">
|
||||
<p className="text-sm text-bolt-elements-textSecondary mb-10">
|
||||
Disclaimer: Experimental features may be unstable and are subject to change.
|
||||
</p>
|
||||
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<span className="text-bolt-elements-textPrimary">Experimental Providers</span>
|
||||
<Switch className="ml-auto" checked={isLocalModel} onCheckedChange={enableLocalModels} />
|
||||
<div className="flex flex-col">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<span className="text-bolt-elements-textPrimary">Experimental Providers</span>
|
||||
<Switch className="ml-auto" checked={isLocalModel} onCheckedChange={enableLocalModels} />
|
||||
</div>
|
||||
<p className="text-xs text-bolt-elements-textTertiary mb-4">
|
||||
Enable experimental providers such as Ollama, LMStudio, and OpenAILike.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-start justify-between pt-4 mb-2 gap-2">
|
||||
<div className="flex-1 max-w-[200px]">
|
||||
<span className="text-bolt-elements-textPrimary">Prompt Library</span>
|
||||
<p className="text-sm text-bolt-elements-textSecondary mb-4">
|
||||
<p className="text-xs text-bolt-elements-textTertiary mb-4">
|
||||
Choose a prompt from the library to use as the system prompt.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user