Compare commits

...

2 Commits

24 changed files with 267 additions and 207 deletions

View File

@@ -23,6 +23,7 @@ export type AgentForm = {
instructions: string | null; instructions: string | null;
model: string | null; model: string | null;
model_parameters: AgentModelParameters; model_parameters: AgentModelParameters;
conversation_starters: string[];
tools?: string[]; tools?: string[];
provider?: AgentProvider | OptionWithIcon; provider?: AgentProvider | OptionWithIcon;
agent_ids?: string[]; agent_ids?: string[];

View File

@@ -4,7 +4,7 @@ import { useGetEndpointsQuery, useGetStartupConfig } from 'librechat-data-provid
import type * as t from 'librechat-data-provider'; import type * as t from 'librechat-data-provider';
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import { useChatContext, useAgentsMapContext, useAssistantsMapContext } from '~/Providers'; import { useChatContext, useAgentsMapContext, useAssistantsMapContext } from '~/Providers';
import { useGetAssistantDocsQuery } from '~/data-provider'; import { useGetAssistantDocsQuery, useGetAgentByIdQuery } from '~/data-provider';
import ConvoIcon from '~/components/Endpoints/ConvoIcon'; import ConvoIcon from '~/components/Endpoints/ConvoIcon';
import { getIconEndpoint, getEntity, cn } from '~/utils'; import { getIconEndpoint, getEntity, cn } from '~/utils';
import { useLocalize, useSubmitMessage } from '~/hooks'; import { useLocalize, useSubmitMessage } from '~/hooks';
@@ -12,8 +12,22 @@ import { TooltipAnchor } from '~/components/ui';
import { BirthdayIcon } from '~/components/svg'; import { BirthdayIcon } from '~/components/svg';
import ConvoStarter from './ConvoStarter'; import ConvoStarter from './ConvoStarter';
const getSequentialFromRandom = (arr: string[], count: number) => {
if (arr.length <= count) {
return arr;
}
const maxStartIndex = arr.length - count;
const startIndex = Math.floor(Math.random() * (maxStartIndex + 1));
return arr.slice(startIndex, startIndex + count);
};
export default function Landing({ Header }: { Header?: ReactNode }) { export default function Landing({ Header }: { Header?: ReactNode }) {
const { conversation } = useChatContext(); const { conversation } = useChatContext();
const { data: agentData } = useGetAgentByIdQuery(conversation?.agent_id ?? '', {
enabled: typeof conversation?.agent_id === 'string' && conversation.agent_id.length > 0,
});
const agentsMap = useAgentsMapContext(); const agentsMap = useAgentsMapContext();
const assistantMap = useAssistantsMapContext(); const assistantMap = useAssistantsMapContext();
const { data: startupConfig } = useGetStartupConfig(); const { data: startupConfig } = useGetStartupConfig();
@@ -51,6 +65,10 @@ export default function Landing({ Header }: { Header?: ReactNode }) {
? (entity as t.Agent | undefined)?.avatar?.filepath ?? '' ? (entity as t.Agent | undefined)?.avatar?.filepath ?? ''
: ((entity as t.Assistant | undefined)?.metadata?.avatar as string | undefined) ?? ''; : ((entity as t.Assistant | undefined)?.metadata?.avatar as string | undefined) ?? '';
const conversation_starters = useMemo(() => { const conversation_starters = useMemo(() => {
if (isAgent && agentData?.conversation_starters) {
return agentData.conversation_starters;
}
/* The user made updates, use client-side cache, or they exist in an Agent */ /* The user made updates, use client-side cache, or they exist in an Agent */
if (entity && (entity.conversation_starters?.length ?? 0) > 0) { if (entity && (entity.conversation_starters?.length ?? 0) > 0) {
return entity.conversation_starters; return entity.conversation_starters;
@@ -87,6 +105,11 @@ export default function Landing({ Header }: { Header?: ReactNode }) {
return localize('com_nav_welcome_message'); return localize('com_nav_welcome_message');
}; };
const randomizedStarters = useMemo(
() => getSequentialFromRandom(conversation_starters, 4),
[conversation_starters],
);
return ( return (
<div className="relative h-full"> <div className="relative h-full">
<div className="absolute left-0 right-0">{Header != null ? Header : null}</div> <div className="absolute left-0 right-0">{Header != null ? Header : null}</div>
@@ -127,16 +150,10 @@ export default function Landing({ Header }: { Header?: ReactNode }) {
</h2> </h2>
)} )}
<div className="mt-8 flex flex-wrap justify-center gap-3 px-4"> <div className="mt-8 flex flex-wrap justify-center gap-3 px-4">
{conversation_starters.length > 0 && {randomizedStarters.length > 0 &&
conversation_starters randomizedStarters.map((text: string, index: number) => (
.slice(0, Constants.MAX_CONVO_STARTERS) <ConvoStarter key={index} text={text} onClick={() => sendConversationStarter(text)} />
.map((text: string, index: number) => ( ))}
<ConvoStarter
key={index}
text={text}
onClick={() => sendConversationStarter(text)}
/>
))}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -16,6 +16,7 @@ import { useCreateAgentMutation, useUpdateAgentMutation } from '~/data-provider'
import { useLocalize, useAuthContext, useHasAccess } from '~/hooks'; import { useLocalize, useAuthContext, useHasAccess } from '~/hooks';
import { useToastContext, useFileMapContext } from '~/Providers'; import { useToastContext, useFileMapContext } from '~/Providers';
import { icons } from '~/components/Chat/Menus/Endpoints/Icons'; import { icons } from '~/components/Chat/Menus/Endpoints/Icons';
import { AgentConversationStarters } from '~/components/ui';
import Action from '~/components/SidePanel/Builder/Action'; import Action from '~/components/SidePanel/Builder/Action';
import { ToolSelectDialog } from '~/components/Tools'; import { ToolSelectDialog } from '~/components/Tools';
import DuplicateAgent from './DuplicateAgent'; import DuplicateAgent from './DuplicateAgent';
@@ -33,7 +34,7 @@ import { Panel } from '~/common';
const labelClass = 'mb-2 text-token-text-primary block font-medium'; const labelClass = 'mb-2 text-token-text-primary block font-medium';
const inputClass = cn( const inputClass = cn(
defaultTextProps, defaultTextProps,
'flex w-full px-3 py-2 border-border-light bg-surface-secondary focus-visible:ring-2 focus-visible:ring-ring-primary', 'flex w-full px-3 py-2 dark:border-surface-secondary dark:bg-surface-secondary rounded-xl mb-2 transition-all duration-200',
removeFocusOutlines, removeFocusOutlines,
); );
@@ -310,6 +311,22 @@ export default function AgentConfig({
)} )}
/> />
</div> </div>
{/* Conversation Starters */}
<div className="relative mb-6">
{/* the label of conversation starters is in the component */}
<Controller
name="conversation_starters"
control={control}
defaultValue={[]}
render={({ field }) => (
<AgentConversationStarters
field={field}
inputClass={inputClass}
labelClass={labelClass}
/>
)}
/>
</div>
{/* Model and Provider */} {/* Model and Provider */}
<div className="mb-4"> <div className="mb-4">
<label className={labelClass} htmlFor="provider"> <label className={labelClass} htmlFor="provider">

View File

@@ -126,6 +126,7 @@ export default function AgentPanel({
model: _model, model: _model,
model_parameters, model_parameters,
provider: _provider, provider: _provider,
conversation_starters: starters,
agent_ids, agent_ids,
end_after_tools, end_after_tools,
hide_sequential_outputs, hide_sequential_outputs,
@@ -146,6 +147,7 @@ export default function AgentPanel({
tools, tools,
provider, provider,
model_parameters, model_parameters,
conversation_starters: starters.filter((starter) => starter.trim() !== ''),
agent_ids, agent_ids,
end_after_tools, end_after_tools,
hide_sequential_outputs, hide_sequential_outputs,
@@ -169,6 +171,7 @@ export default function AgentPanel({
tools, tools,
provider, provider,
model_parameters, model_parameters,
conversation_starters: starters.filter((starter) => starter.trim() !== ''),
agent_ids, agent_ids,
end_after_tools, end_after_tools,
hide_sequential_outputs, hide_sequential_outputs,

View File

@@ -89,6 +89,15 @@ export default function AgentSelect({
return; return;
} }
if (
name === 'conversation_starters' &&
Array.isArray(value) &&
value.every((item) => typeof item === 'string')
) {
formValues[name] = value;
return;
}
if (typeof value !== 'number' && typeof value !== 'object') { if (typeof value !== 'number' && typeof value !== 'object') {
formValues[name] = value; formValues[name] = value;
} }

View File

@@ -1,155 +0,0 @@
import React, { useRef, useState } from 'react';
import { Plus, X } from 'lucide-react';
import { Transition } from 'react-transition-group';
import { Constants } from 'librechat-data-provider';
import { TooltipAnchor } from '~/components/ui';
import { useLocalize } from '~/hooks';
interface AssistantConversationStartersProps {
field: {
value: string[];
onChange: (value: string[]) => void;
};
inputClass: string;
labelClass: string;
}
const AssistantConversationStarters: React.FC<AssistantConversationStartersProps> = ({
field,
inputClass,
labelClass,
}) => {
const localize = useLocalize();
const inputRefs = useRef<(HTMLInputElement | null)[]>([]);
const nodeRef = useRef(null);
const [newStarter, setNewStarter] = useState('');
const handleAddStarter = () => {
if (newStarter.trim() && field.value.length < Constants.MAX_CONVO_STARTERS) {
const newValues = [newStarter, ...field.value];
field.onChange(newValues);
setNewStarter('');
}
};
const handleDeleteStarter = (index: number) => {
const newValues = field.value.filter((_, i) => i !== index);
field.onChange(newValues);
};
const defaultStyle = {
transition: 'opacity 200ms ease-in-out',
opacity: 0,
};
const triggerShake = (element: HTMLElement) => {
element.classList.remove('shake');
void element.offsetWidth;
element.classList.add('shake');
setTimeout(() => {
element.classList.remove('shake');
}, 200);
};
const transitionStyles = {
entering: { opacity: 1 },
entered: { opacity: 1 },
exiting: { opacity: 0 },
exited: { opacity: 0 },
};
const hasReachedMax = field.value.length >= Constants.MAX_CONVO_STARTERS;
return (
<div className="relative">
<label className={labelClass} htmlFor="conversation_starters">
{localize('com_assistants_conversation_starters')}
</label>
<div className="mt-4 space-y-2">
{/* Persistent starter, used for creating only */}
<div className="relative">
<input
ref={(el) => (inputRefs.current[0] = el)}
value={newStarter}
maxLength={64}
className={`${inputClass} pr-10`}
type="text"
placeholder={
hasReachedMax
? localize('com_assistants_max_starters_reached')
: localize('com_assistants_conversation_starters_placeholder')
}
onChange={(e) => setNewStarter(e.target.value)}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault();
if (hasReachedMax) {
triggerShake(e.currentTarget);
} else {
handleAddStarter();
}
}
}}
/>
<Transition
nodeRef={nodeRef}
in={field.value.length < Constants.MAX_CONVO_STARTERS}
timeout={200}
unmountOnExit
>
{(state: string) => (
<div
ref={nodeRef}
style={{
...defaultStyle,
...transitionStyles[state as keyof typeof transitionStyles],
transition: state === 'entering' ? 'none' : defaultStyle.transition,
}}
className="absolute right-1 top-1"
>
<TooltipAnchor
side="top"
description={
hasReachedMax
? localize('com_assistants_max_starters_reached')
: localize('com_ui_add')
}
className="flex size-7 items-center justify-center rounded-lg transition-colors duration-200 hover:bg-surface-hover"
onClick={handleAddStarter}
disabled={hasReachedMax}
>
<Plus className="size-4" />
</TooltipAnchor>
</div>
)}
</Transition>
</div>
{field.value.map((starter, index) => (
<div key={index} className="relative">
<input
ref={(el) => (inputRefs.current[index + 1] = el)}
value={starter}
onChange={(e) => {
const newValue = [...field.value];
newValue[index] = e.target.value;
field.onChange(newValue);
}}
className={`${inputClass} pr-10`}
type="text"
maxLength={64}
/>
<TooltipAnchor
side="top"
description={localize('com_ui_delete')}
className="absolute right-1 top-1 flex size-7 items-center justify-center rounded-lg transition-colors duration-200 hover:bg-surface-hover"
onClick={() => handleDeleteStarter(index)}
>
<X className="size-4" />
</TooltipAnchor>
</div>
))}
</div>
</div>
);
};
export default AssistantConversationStarters;

View File

@@ -14,13 +14,12 @@ import type { FunctionTool, TConfig, TPlugin } from 'librechat-data-provider';
import type { AssistantForm, AssistantPanelProps } from '~/common'; import type { AssistantForm, AssistantPanelProps } from '~/common';
import { useCreateAssistantMutation, useUpdateAssistantMutation } from '~/data-provider'; import { useCreateAssistantMutation, useUpdateAssistantMutation } from '~/data-provider';
import { cn, cardStyle, defaultTextProps, removeFocusOutlines } from '~/utils'; import { cn, cardStyle, defaultTextProps, removeFocusOutlines } from '~/utils';
import AssistantConversationStarters from './AssistantConversationStarters'; import { SelectDropDown, AgentConversationStarters } from '~/components/ui';
import { useAssistantsMapContext, useToastContext } from '~/Providers'; import { useAssistantsMapContext, useToastContext } from '~/Providers';
import { useSelectAssistant, useLocalize } from '~/hooks'; import { useSelectAssistant, useLocalize } from '~/hooks';
import { ToolSelectDialog } from '~/components/Tools'; import { ToolSelectDialog } from '~/components/Tools';
import CapabilitiesForm from './CapabilitiesForm'; import CapabilitiesForm from './CapabilitiesForm';
import AppendDateCheckbox from './AppendDateCheckbox'; import AppendDateCheckbox from './AppendDateCheckbox';
import { SelectDropDown } from '~/components/ui';
import AssistantAvatar from './AssistantAvatar'; import AssistantAvatar from './AssistantAvatar';
import AssistantSelect from './AssistantSelect'; import AssistantSelect from './AssistantSelect';
import ContextButton from './ContextButton'; import ContextButton from './ContextButton';
@@ -339,7 +338,7 @@ export default function AssistantPanel({
control={control} control={control}
defaultValue={[]} defaultValue={[]}
render={({ field }) => ( render={({ field }) => (
<AssistantConversationStarters <AgentConversationStarters
field={field} field={field}
inputClass={inputClass} inputClass={inputClass}
labelClass={labelClass} labelClass={labelClass}

View File

@@ -0,0 +1,165 @@
import React, { useRef, useState, useEffect, DragEvent } from 'react';
import { X, GripVertical } from 'lucide-react';
import { Constants } from 'librechat-data-provider';
import { TooltipAnchor } from './Tooltip';
import { useLocalize } from '~/hooks';
import { motion, AnimatePresence } from 'framer-motion';
interface AgentConversationStartersProps {
field: {
value: string[];
onChange: (value: string[]) => void;
};
inputClass: string;
labelClass: string;
}
export default function AgentConversationStarters({
field,
inputClass,
labelClass,
}: AgentConversationStartersProps) {
const localize = useLocalize();
const inputRefs = useRef<(HTMLInputElement | null)[]>([]);
const [dragIndex, setDragIndex] = useState<number | null>(null);
const [dragOverIndex, setDragOverIndex] = useState<number | null>(null);
const [isCollapsed, setIsCollapsed] = useState<boolean>(true);
useEffect(() => {
if (field.value.length === 0) {
field.onChange(['']);
}
}, [field.value, field]);
const handleDeleteStarter = (index: number) => {
if (!field.value[index]) {
return;
}
const newValues = field.value.filter((_, i) => i !== index);
if (newValues.length === 0) {
newValues.push('');
}
field.onChange(newValues);
};
const handleStarterChange = (value: string, index: number) => {
const newValue = [...field.value];
newValue[index] = value;
if (
index === field.value.length - 1 &&
value.trim() &&
field.value.length < Constants.MAX_CONVO_STARTERS
) {
newValue.push('');
}
field.onChange(newValue);
};
const handleBlur = (index: number) => {
if (!field.value[index] && index !== field.value.length - 1) {
const newValues = field.value.filter((val, i) => i !== index || val.trim() !== '');
if (newValues.length === 0) {
newValues.push('');
}
field.onChange(newValues);
}
};
const handleDragStart = (index: number) => (e: DragEvent<HTMLDivElement>) => {
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/plain', String(index));
setDragIndex(index);
};
const handleDragEnd = () => {
setDragIndex(null);
setDragOverIndex(null);
};
const handleDragOver = (index: number) => (e: DragEvent<HTMLDivElement>) => {
e.preventDefault();
setDragOverIndex(index);
};
const handleDrop = (index: number) => (e: DragEvent<HTMLDivElement>) => {
e.preventDefault();
if (dragIndex === null || dragIndex === index) {
return;
}
const updated = [...field.value];
const [removed] = updated.splice(dragIndex, 1);
updated.splice(index, 0, removed);
field.onChange(updated);
setDragIndex(null);
setDragOverIndex(null);
};
const getDisplayValue = (starter: string, index: number) => {
if (dragIndex === null || dragOverIndex === null) {
return starter;
}
if (index === dragOverIndex && dragIndex !== dragOverIndex) {
return field.value[dragIndex];
}
if (index === dragIndex && dragIndex !== dragOverIndex) {
return '';
}
return starter;
};
return (
<div className="relative">
<label className={labelClass} htmlFor="conversation_starters">
{localize('com_agents_conversation_starters')}
</label>
<div className="mt-4 space-y-2">
<AnimatePresence>
{field.value.map((starter, index) => (
<motion.div
key={index}
className={`hover:bg-accent-primary/5 group relative flex h-10 transform-gpu
items-center rounded-lg transition-transform duration-300
ease-in-out
${dragIndex === index ? 'scale-[0.98] opacity-50' : ''}
${dragOverIndex === index ? 'bg-accent-primary/10 shadow-sm' : ''}
${dragIndex !== null ? 'cursor-grabbing' : ''}`}
draggable
data-index={index}
onDragStart={handleDragStart(index)}
onDragEnd={handleDragEnd}
onDragOver={handleDragOver(index)}
onDrop={handleDrop(index)}
initial={{ opacity: 0, y: -10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
transition={{ type: 'spring', stiffness: 300, damping: 20 }}
layout
>
<div className="flex h-full cursor-grab items-center justify-center px-2 opacity-60 transition-opacity group-hover:opacity-100">
<GripVertical className="size-4 text-text-secondary" />
</div>
<input
ref={(el) => (inputRefs.current[index] = el)}
value={getDisplayValue(starter, index)}
onChange={(e) => handleStarterChange(e.target.value, index)}
onBlur={() => handleBlur(index)}
className={`${inputClass} relative h-full flex-1 pr-10 transition-colors`}
type="text"
maxLength={64}
/>
<TooltipAnchor
side="top"
description={localize('com_ui_delete')}
className="absolute bottom-[0.55rem] right-1 flex size-7 items-center justify-center rounded-lg transition-colors duration-200 hover:bg-surface-hover"
onClick={() => handleDeleteStarter(index)}
disabled={!starter.trim()}
>
<X className="size-4" />
</TooltipAnchor>
</motion.div>
))}
</AnimatePresence>
</div>
</div>
);
}

View File

@@ -36,3 +36,4 @@ export { default as ModelParameters } from './ModelParameters';
export { default as InputWithDropdown } from './InputWithDropDown'; export { default as InputWithDropdown } from './InputWithDropDown';
export { default as SelectDropDownPop } from './SelectDropDownPop'; export { default as SelectDropDownPop } from './SelectDropDownPop';
export { default as MultiSelectDropDown } from './MultiSelectDropDown'; export { default as MultiSelectDropDown } from './MultiSelectDropDown';
export { default as AgentConversationStarters } from './AgentConversationStarters';

View File

@@ -628,8 +628,8 @@ export default {
com_download_expires: 'انقر هنا للتنزيل - تنتهي الصلاحية في {0}', com_download_expires: 'انقر هنا للتنزيل - تنتهي الصلاحية في {0}',
com_download_expired: 'انتهت صلاحية التنزيل', com_download_expired: 'انتهت صلاحية التنزيل',
com_click_to_download: '(انقر هنا للتنزيل)', com_click_to_download: '(انقر هنا للتنزيل)',
com_assistants_conversation_starters_placeholder: 'أدخل بداية المحادثة', com_agents_conversation_starters_placeholder: 'أدخل بداية المحادثة',
com_assistants_conversation_starters: 'بدء المحادثات', com_agents_conversation_starters: 'بدء المحادثات',
com_assistants_code_interpreter_info: com_assistants_code_interpreter_info:
'يُمكّن مُفسِّر الشفرة المساعد من كتابة وتشغيل الشفرة البرمجية. يمكن لهذه الأداة معالجة الملفات ذات البيانات والتنسيقات المتنوعة، وإنشاء ملفات مثل الرسوم البيانية', 'يُمكّن مُفسِّر الشفرة المساعد من كتابة وتشغيل الشفرة البرمجية. يمكن لهذه الأداة معالجة الملفات ذات البيانات والتنسيقات المتنوعة، وإنشاء ملفات مثل الرسوم البيانية',
com_sidepanel_agent_builder: 'بانٍ المساعد', com_sidepanel_agent_builder: 'بانٍ المساعد',
@@ -698,7 +698,7 @@ export default {
com_ui_add_model_preset: 'إضافة نموذج أو إعداد مسبق للرد الإضافي', com_ui_add_model_preset: 'إضافة نموذج أو إعداد مسبق للرد الإضافي',
com_ui_loading: 'جارِ التحميل...', com_ui_loading: 'جارِ التحميل...',
com_ui_all_proper: 'الكل', com_ui_all_proper: 'الكل',
com_assistants_max_starters_reached: 'تم الوصول إلى الحد الأقصى لبادئات المحادثة', com_agents_max_starters_reached: 'تم الوصول إلى الحد الأقصى لبادئات المحادثة',
com_ui_revoke_keys: 'إلغاء المفاتيح', com_ui_revoke_keys: 'إلغاء المفاتيح',
com_ui_revoke_key_endpoint: 'إلغاء المفتاح لـ {0}', com_ui_revoke_key_endpoint: 'إلغاء المفتاح لـ {0}',
com_ui_revoke_key_confirm: 'هل أنت متأكد من إلغاء هذا المفتاح؟', com_ui_revoke_key_confirm: 'هل أنت متأكد من إلغاء هذا المفتاح؟',

View File

@@ -85,8 +85,8 @@ export default {
com_assistants_update_error: 'Houve um erro ao atualizar seu assistente.', com_assistants_update_error: 'Houve um erro ao atualizar seu assistente.',
com_assistants_create_success: 'Criado com sucesso', com_assistants_create_success: 'Criado com sucesso',
com_assistants_create_error: 'Houve um erro ao criar seu assistente.', com_assistants_create_error: 'Houve um erro ao criar seu assistente.',
com_assistants_conversation_starters: 'Iniciadores de Conversa', com_agents_conversation_starters: 'Iniciadores de Conversa',
com_assistants_conversation_starters_placeholder: 'Digite um iniciador de conversa', com_agents_conversation_starters_placeholder: 'Digite um iniciador de conversa',
com_sidepanel_agent_builder: 'Construtor de Agente', com_sidepanel_agent_builder: 'Construtor de Agente',
com_agents_name_placeholder: 'Opcional: O nome do agente', com_agents_name_placeholder: 'Opcional: O nome do agente',
com_agents_description_placeholder: 'Opcional: Descreva seu Agente aqui', com_agents_description_placeholder: 'Opcional: Descreva seu Agente aqui',
@@ -247,7 +247,7 @@ export default {
com_ui_mention: com_ui_mention:
'Mencione um endpoint, assistente ou predefinição para alternar rapidamente para ele', 'Mencione um endpoint, assistente ou predefinição para alternar rapidamente para ele',
com_ui_add_model_preset: 'Adicionar um modelo ou predefinição para uma resposta adicional', com_ui_add_model_preset: 'Adicionar um modelo ou predefinição para uma resposta adicional',
com_assistants_max_starters_reached: 'Número máximo de iniciadores de conversa atingido', com_agents_max_starters_reached: 'Número máximo de iniciadores de conversa atingido',
com_ui_regenerate: 'Regenerar', com_ui_regenerate: 'Regenerar',
com_ui_continue: 'Continuar', com_ui_continue: 'Continuar',
com_ui_edit: 'Editar', com_ui_edit: 'Editar',

View File

@@ -780,9 +780,9 @@ export default {
com_click_to_download: '(hier klicken zum Herunterladen)', com_click_to_download: '(hier klicken zum Herunterladen)',
com_download_expires: '(hier klicken zum Herunterladen - läuft ab am {0})', com_download_expires: '(hier klicken zum Herunterladen - läuft ab am {0})',
com_sidepanel_agent_builder: 'Agenten Ersteller', com_sidepanel_agent_builder: 'Agenten Ersteller',
com_assistants_conversation_starters_placeholder: 'Gib einen Gesprächseinstieg ein', com_agents_conversation_starters_placeholder: 'Gib einen Gesprächseinstieg ein',
com_agents_name_placeholder: 'Optional: Der Name des Agenten', com_agents_name_placeholder: 'Optional: Der Name des Agenten',
com_assistants_conversation_starters: 'Gesprächseinstiege', com_agents_conversation_starters: 'Gesprächseinstiege',
com_agents_description_placeholder: 'Optional: Beschreibe hier deinen Agenten', com_agents_description_placeholder: 'Optional: Beschreibe hier deinen Agenten',
com_agents_search_name: 'Agenten nach Namen suchen', com_agents_search_name: 'Agenten nach Namen suchen',
com_agents_instructions_placeholder: 'Die Systemanweisungen, die der Agent verwendet', com_agents_instructions_placeholder: 'Die Systemanweisungen, die der Agent verwendet',
@@ -812,7 +812,7 @@ export default {
com_ui_select_provider_first: 'Wähle zuerst einen Anbieter', com_ui_select_provider_first: 'Wähle zuerst einen Anbieter',
com_ui_select_provider: 'Wähle einen Anbieter', com_ui_select_provider: 'Wähle einen Anbieter',
com_ui_revoke_keys: 'Schlüssel widerrufen', com_ui_revoke_keys: 'Schlüssel widerrufen',
com_assistants_max_starters_reached: 'Maximale Anzahl an Gesprächseinstiegen erreicht', com_agents_max_starters_reached: 'Maximale Anzahl an Gesprächseinstiegen erreicht',
com_ui_revoke_keys_confirm: 'Bist du sicher, dass du alle Schlüssel widerrufen möchtest?', com_ui_revoke_keys_confirm: 'Bist du sicher, dass du alle Schlüssel widerrufen möchtest?',
com_ui_revoke_key_confirm: 'Bist du sicher, dass du diesen Schlüssel widerrufen möchtest?', com_ui_revoke_key_confirm: 'Bist du sicher, dass du diesen Schlüssel widerrufen möchtest?',
com_ui_revoke_key_endpoint: 'API-Schlüssel für {0} widerrufen', com_ui_revoke_key_endpoint: 'API-Schlüssel für {0} widerrufen',

View File

@@ -105,8 +105,8 @@ export default {
com_assistants_update_error: 'There was an error updating your assistant.', com_assistants_update_error: 'There was an error updating your assistant.',
com_assistants_create_success: 'Successfully created', com_assistants_create_success: 'Successfully created',
com_assistants_create_error: 'There was an error creating your assistant.', com_assistants_create_error: 'There was an error creating your assistant.',
com_assistants_conversation_starters: 'Conversation Starters', com_agents_conversation_starters: 'Conversation Starters',
com_assistants_conversation_starters_placeholder: 'Enter a conversation starter', com_agents_conversation_starters_placeholder: 'Enter a conversation starter',
com_sidepanel_agent_builder: 'Agent Builder', com_sidepanel_agent_builder: 'Agent Builder',
com_agents_name_placeholder: 'Optional: The name of the agent', com_agents_name_placeholder: 'Optional: The name of the agent',
com_agents_description_placeholder: 'Optional: Describe your Agent here', com_agents_description_placeholder: 'Optional: Describe your Agent here',
@@ -300,7 +300,7 @@ export default {
com_ui_fork_from_message: 'Select a fork option', com_ui_fork_from_message: 'Select a fork option',
com_ui_mention: 'Mention an endpoint, assistant, or preset to quickly switch to it', com_ui_mention: 'Mention an endpoint, assistant, or preset to quickly switch to it',
com_ui_add_model_preset: 'Add a model or preset for an additional response', com_ui_add_model_preset: 'Add a model or preset for an additional response',
com_assistants_max_starters_reached: 'Max number of conversation starters reached', com_agents_max_starters_reached: 'Max number of conversation starters reached',
com_ui_duplication_success: 'Successfully duplicated conversation', com_ui_duplication_success: 'Successfully duplicated conversation',
com_ui_duplication_processing: 'Duplicating conversation...', com_ui_duplication_processing: 'Duplicating conversation...',
com_ui_duplication_error: 'There was an error duplicating the conversation', com_ui_duplication_error: 'There was an error duplicating the conversation',

View File

@@ -681,12 +681,12 @@ export default {
com_click_to_download: '(haga clic aquí para descargar)', com_click_to_download: '(haga clic aquí para descargar)',
com_assistants_conversation_starters: 'Iniciadores de Conversación', com_agents_conversation_starters: 'Iniciadores de Conversación',
com_assistants_code_interpreter_info: com_assistants_code_interpreter_info:
'El Intérprete de Código permite al asistente escribir y ejecutar código. Esta herramienta puede procesar archivos con diversos formatos y datos, y generar archivos como gráficos.', 'El Intérprete de Código permite al asistente escribir y ejecutar código. Esta herramienta puede procesar archivos con diversos formatos y datos, y generar archivos como gráficos.',
com_assistants_conversation_starters_placeholder: 'Ingrese un iniciador de conversación', com_agents_conversation_starters_placeholder: 'Ingrese un iniciador de conversación',
com_sidepanel_agent_builder: 'Constructor de Agentes', com_sidepanel_agent_builder: 'Constructor de Agentes',
@@ -820,7 +820,7 @@ export default {
com_ui_add_model_preset: com_ui_add_model_preset:
'Agregar un modelo o configuración preestablecida para una respuesta adicional', 'Agregar un modelo o configuración preestablecida para una respuesta adicional',
com_assistants_max_starters_reached: 'Se alcanzó el número máximo de iniciadores de conversación', com_agents_max_starters_reached: 'Se alcanzó el número máximo de iniciadores de conversación',
com_ui_loading: 'Cargando...', com_ui_loading: 'Cargando...',

View File

@@ -778,10 +778,10 @@ export default {
com_download_expired: 'Téléchargement expiré', com_download_expired: 'Téléchargement expiré',
com_download_expires: '(cliquez ici pour télécharger - expire le {0})', com_download_expires: '(cliquez ici pour télécharger - expire le {0})',
com_click_to_download: '(cliquez ici pour télécharger)', com_click_to_download: '(cliquez ici pour télécharger)',
com_assistants_conversation_starters: 'Suggestions de conversation', com_agents_conversation_starters: 'Suggestions de conversation',
com_assistants_code_interpreter_info: com_assistants_code_interpreter_info:
'L\'interpréteur de code permet à l\'assistant d\'écrire et d\'exécuter du code. Cet outil peut traiter des fichiers avec différents formats de données et générer des fichiers tels que des graphiques.', 'L\'interpréteur de code permet à l\'assistant d\'écrire et d\'exécuter du code. Cet outil peut traiter des fichiers avec différents formats de données et générer des fichiers tels que des graphiques.',
com_assistants_conversation_starters_placeholder: 'Saisissez une amorce de conversation', com_agents_conversation_starters_placeholder: 'Saisissez une amorce de conversation',
com_sidepanel_agent_builder: 'Constructeur d\'agent', com_sidepanel_agent_builder: 'Constructeur d\'agent',
com_agents_name_placeholder: 'Facultatif : Le nom de l\'agent', com_agents_name_placeholder: 'Facultatif : Le nom de l\'agent',
com_agents_instructions_placeholder: 'Les instructions système que l\'agent utilise', com_agents_instructions_placeholder: 'Les instructions système que l\'agent utilise',
@@ -815,7 +815,7 @@ export default {
'Utilisez `{{current_date}}` pour la date actuelle et `{{current_user}}` pour votre nom de compte.', 'Utilisez `{{current_date}}` pour la date actuelle et `{{current_user}}` pour votre nom de compte.',
com_ui_select_search_region: 'Rechercher une région par nom', com_ui_select_search_region: 'Rechercher une région par nom',
com_ui_dropdown_variables: 'Variables déroulantes :', com_ui_dropdown_variables: 'Variables déroulantes :',
com_assistants_max_starters_reached: 'Nombre maximum de démarreurs de conversation atteint', com_agents_max_starters_reached: 'Nombre maximum de démarreurs de conversation atteint',
com_ui_dropdown_variables_info: com_ui_dropdown_variables_info:
'Créez des menus déroulants personnalisés pour vos prompts : `{{nom_variable:option1|option2|option3}}`', 'Créez des menus déroulants personnalisés pour vos prompts : `{{nom_variable:option1|option2|option3}}`',
com_ui_revoke_keys: 'Révoquer les clés', com_ui_revoke_keys: 'Révoquer les clés',

View File

@@ -660,10 +660,10 @@ export default {
com_download_expired: 'download scaduto', com_download_expired: 'download scaduto',
com_download_expires: '(clicca qui per scaricare - scade il {0})', com_download_expires: '(clicca qui per scaricare - scade il {0})',
com_click_to_download: 'clicca qui per scaricare', com_click_to_download: 'clicca qui per scaricare',
com_assistants_conversation_starters: 'Spunti di Conversazione', com_agents_conversation_starters: 'Spunti di Conversazione',
com_assistants_code_interpreter_info: com_assistants_code_interpreter_info:
'L\'Interprete Codice permette all\'assistente di scrivere ed eseguire codice. Questo strumento può elaborare file con diversi formati e tipi di dati, e generare file come grafici.', 'L\'Interprete Codice permette all\'assistente di scrivere ed eseguire codice. Questo strumento può elaborare file con diversi formati e tipi di dati, e generare file come grafici.',
com_assistants_conversation_starters_placeholder: 'Inserisci un argomento di conversazione', com_agents_conversation_starters_placeholder: 'Inserisci un argomento di conversazione',
com_sidepanel_agent_builder: 'Costruttore Agente', com_sidepanel_agent_builder: 'Costruttore Agente',
com_agents_name_placeholder: 'Opzionale: Il nome dell\'agente', com_agents_name_placeholder: 'Opzionale: Il nome dell\'agente',
com_agents_description_placeholder: 'Opzionale: Descrivi qui il tuo Agente', com_agents_description_placeholder: 'Opzionale: Descrivi qui il tuo Agente',
@@ -737,7 +737,7 @@ export default {
com_ui_add_model_preset: 'Aggiungi un modello o una preimpostazione per una risposta aggiuntiva', com_ui_add_model_preset: 'Aggiungi un modello o una preimpostazione per una risposta aggiuntiva',
com_ui_loading: 'Caricamento...', com_ui_loading: 'Caricamento...',
com_ui_all_proper: 'Tutto', com_ui_all_proper: 'Tutto',
com_assistants_max_starters_reached: 'Raggiunto il numero massimo di conversazioni iniziali', com_agents_max_starters_reached: 'Raggiunto il numero massimo di conversazioni iniziali',
com_ui_revoke_keys: 'Revoca Chiavi', com_ui_revoke_keys: 'Revoca Chiavi',
com_ui_revoke_keys_confirm: 'Sei sicuro di voler revocare tutte le chiavi?', com_ui_revoke_keys_confirm: 'Sei sicuro di voler revocare tutte le chiavi?',
com_ui_revoke_key_endpoint: 'Revoca Chiave per {0}', com_ui_revoke_key_endpoint: 'Revoca Chiave per {0}',

View File

@@ -81,8 +81,8 @@ export default {
com_assistants_update_error: 'アシスタントの更新中にエラーが発生しました。', com_assistants_update_error: 'アシスタントの更新中にエラーが発生しました。',
com_assistants_create_success: 'アシスタントが正常に作成されました。', com_assistants_create_success: 'アシスタントが正常に作成されました。',
com_assistants_create_error: 'アシスタントの作成中にエラーが発生しました。', com_assistants_create_error: 'アシスタントの作成中にエラーが発生しました。',
com_assistants_conversation_starters: '会話のきっかけ', com_agents_conversation_starters: '会話のきっかけ',
com_assistants_conversation_starters_placeholder: '会話のきっかけを入力してください', com_agents_conversation_starters_placeholder: '会話のきっかけを入力してください',
com_sidepanel_agent_builder: 'エージェントビルダー', com_sidepanel_agent_builder: 'エージェントビルダー',
com_agents_name_placeholder: 'オプション: エージェントの名前', com_agents_name_placeholder: 'オプション: エージェントの名前',
com_agents_description_placeholder: 'オプション: エージェントの説明を入力してください', com_agents_description_placeholder: 'オプション: エージェントの説明を入力してください',
@@ -245,7 +245,7 @@ export default {
com_ui_mention: com_ui_mention:
'エンドポイント、アシスタント、またはプリセットを素早く切り替えるには、それらを言及してください。', 'エンドポイント、アシスタント、またはプリセットを素早く切り替えるには、それらを言及してください。',
com_ui_add_model_preset: '追加の応答のためのモデルまたはプリセットを追加する', com_ui_add_model_preset: '追加の応答のためのモデルまたはプリセットを追加する',
com_assistants_max_starters_reached: '会話の開始が最大数に達しました', com_agents_max_starters_reached: '会話の開始が最大数に達しました',
com_ui_regenerate: '再度 生成する', com_ui_regenerate: '再度 生成する',
com_ui_continue: '続きを生成する', com_ui_continue: '続きを生成する',
com_ui_edit: '編集', com_ui_edit: '編集',

View File

@@ -987,7 +987,7 @@ export default {
com_click_to_download: '(다운로드하려면 클릭하세요)', com_click_to_download: '(다운로드하려면 클릭하세요)',
com_assistants_conversation_starters_placeholder: '대화를 시작할 문구를 입력하세요', com_agents_conversation_starters_placeholder: '대화를 시작할 문구를 입력하세요',
com_download_expires: '(다운로드하려면 클릭하세요 - {0} 후 만료)', com_download_expires: '(다운로드하려면 클릭하세요 - {0} 후 만료)',
@@ -995,7 +995,7 @@ export default {
com_sidepanel_agent_builder: '에이전트 제작기', com_sidepanel_agent_builder: '에이전트 제작기',
com_assistants_conversation_starters: '대화 시작하기', com_agents_conversation_starters: '대화 시작하기',
com_agents_instructions_placeholder: '에이전트가 사용하는 시스템 지침', com_agents_instructions_placeholder: '에이전트가 사용하는 시스템 지침',
@@ -1051,7 +1051,7 @@ export default {
com_ui_add_model_preset: '추가 응답을 위한 모델 또는 프리셋 추가', com_ui_add_model_preset: '추가 응답을 위한 모델 또는 프리셋 추가',
com_assistants_max_starters_reached: '대화 시작 문구 최대 개수에 도달했습니다', com_agents_max_starters_reached: '대화 시작 문구 최대 개수에 도달했습니다',
com_ui_revoke_keys: '키 취소', com_ui_revoke_keys: '키 취소',

View File

@@ -669,9 +669,9 @@ export default {
com_assistants_code_interpreter_info: com_assistants_code_interpreter_info:
'Интерпретатор кода позволяет ассистенту создавать и выполнять код. Этот инструмент может обрабатывать файлы с различными данными и форматами, а также создавать файлы, например графики.', 'Интерпретатор кода позволяет ассистенту создавать и выполнять код. Этот инструмент может обрабатывать файлы с различными данными и форматами, а также создавать файлы, например графики.',
com_assistants_conversation_starters_placeholder: 'Введите начальную фразу для разговора', com_agents_conversation_starters_placeholder: 'Введите начальную фразу для разговора',
com_assistants_conversation_starters: 'Примеры запросов', com_agents_conversation_starters: 'Примеры запросов',
com_sidepanel_agent_builder: 'Конструктор агента', com_sidepanel_agent_builder: 'Конструктор агента',
@@ -801,7 +801,7 @@ export default {
com_ui_add_model_preset: 'Добавить модель или пресет для дополнительного ответа', com_ui_add_model_preset: 'Добавить модель или пресет для дополнительного ответа',
com_assistants_max_starters_reached: 'Достигнуто максимальное количество начальных подсказок', com_agents_max_starters_reached: 'Достигнуто максимальное количество начальных подсказок',
com_ui_all_proper: 'Все', com_ui_all_proper: 'Все',

View File

@@ -76,8 +76,8 @@ export default {
com_assistants_update_error: '更新助手时出现错误。', com_assistants_update_error: '更新助手时出现错误。',
com_assistants_create_success: '已成功创建', com_assistants_create_success: '已成功创建',
com_assistants_create_error: '创建助手时出现错误。', com_assistants_create_error: '创建助手时出现错误。',
com_assistants_conversation_starters: '对话启动器', com_agents_conversation_starters: '对话启动器',
com_assistants_conversation_starters_placeholder: '输入对话启动器', com_agents_conversation_starters_placeholder: '输入对话启动器',
com_sidepanel_agent_builder: '代理构建器', com_sidepanel_agent_builder: '代理构建器',
com_agents_name_placeholder: '可选:代理名称', com_agents_name_placeholder: '可选:代理名称',
com_agents_description_placeholder: '可选:在此描述您的代理', com_agents_description_placeholder: '可选:在此描述您的代理',
@@ -232,7 +232,7 @@ export default {
com_ui_fork_from_message: '选择分叉选项', com_ui_fork_from_message: '选择分叉选项',
com_ui_mention: '提及一个端点、助手或预设以快速切换到它', com_ui_mention: '提及一个端点、助手或预设以快速切换到它',
com_ui_add_model_preset: '添加一个模型或预设以获得额外的回复', com_ui_add_model_preset: '添加一个模型或预设以获得额外的回复',
com_assistants_max_starters_reached: '已达到对话启动器的最大数量', com_agents_max_starters_reached: '已达到对话启动器的最大数量',
com_ui_regenerate: '重新生成', com_ui_regenerate: '重新生成',
com_ui_continue: '继续', com_ui_continue: '继续',
com_ui_edit: '编辑', com_ui_edit: '编辑',

View File

@@ -597,11 +597,11 @@ export default {
com_error_files_upload_canceled: com_error_files_upload_canceled:
'檔案上傳請求已取消。注意:檔案上傳可能仍在處理中,需要手動刪除。', '檔案上傳請求已取消。注意:檔案上傳可能仍在處理中,需要手動刪除。',
com_click_to_download: '(點選此處下載)', com_click_to_download: '(點選此處下載)',
com_assistants_conversation_starters_placeholder: '輸入對話開場白', com_agents_conversation_starters_placeholder: '輸入對話開場白',
com_download_expires: '(點擊此處下載 - {0} 後過期)', com_download_expires: '(點擊此處下載 - {0} 後過期)',
com_sidepanel_agent_builder: '代理建構器', com_sidepanel_agent_builder: '代理建構器',
com_agents_name_placeholder: '選填:代理人的名稱', com_agents_name_placeholder: '選填:代理人的名稱',
com_assistants_conversation_starters: '對話起點', com_agents_conversation_starters: '對話起點',
com_agents_description_placeholder: '選填:在此描述您的代理程式', com_agents_description_placeholder: '選填:在此描述您的代理程式',
com_assistants_code_interpreter_info: com_assistants_code_interpreter_info:
'程式碼解譯器可讓助理撰寫和執行程式碼。此工具能處理各種資料格式的檔案,並產生圖表等檔案。', '程式碼解譯器可讓助理撰寫和執行程式碼。此工具能處理各種資料格式的檔案,並產生圖表等檔案。',
@@ -664,7 +664,7 @@ export default {
com_ui_renaming_var: '重新命名「{0}」', com_ui_renaming_var: '重新命名「{0}」',
com_ui_latest_footer: '讓每個人都能使用 AI', com_ui_latest_footer: '讓每個人都能使用 AI',
com_ui_upload_invalid: '上傳的檔案無效。必須是不超過限制的圖片檔', com_ui_upload_invalid: '上傳的檔案無效。必須是不超過限制的圖片檔',
com_assistants_max_starters_reached: '已達對話起始項目的最大數量', com_agents_max_starters_reached: '已達對話起始項目的最大數量',
com_ui_add_model_preset: '新增模型或預設設定以取得額外回應', com_ui_add_model_preset: '新增模型或預設設定以取得額外回應',
com_ui_upload_invalid_var: '上傳的檔案無效。必須是不超過 {0} MB 的圖片檔案', com_ui_upload_invalid_var: '上傳的檔案無效。必須是不超過 {0} MB 的圖片檔案',
com_ui_loading: '載入中...', com_ui_loading: '載入中...',

View File

@@ -1151,7 +1151,7 @@ export enum Constants {
/** Saved Tag */ /** Saved Tag */
SAVED_TAG = 'Saved', SAVED_TAG = 'Saved',
/** Max number of Conversation starters for Agents/Assistants */ /** Max number of Conversation starters for Agents/Assistants */
MAX_CONVO_STARTERS = 4, MAX_CONVO_STARTERS = 64,
/** Global/instance Project Name */ /** Global/instance Project Name */
GLOBAL_PROJECT_NAME = 'instance', GLOBAL_PROJECT_NAME = 'instance',
/** Delimiter for MCP tools */ /** Delimiter for MCP tools */

View File

@@ -146,6 +146,7 @@ export const defaultAgentFormValues = {
instructions: '', instructions: '',
model: '', model: '',
model_parameters: {}, model_parameters: {},
conversation_starters: [],
tools: [], tools: [],
provider: {}, provider: {},
projectIds: [], projectIds: [],

View File

@@ -229,6 +229,7 @@ export type AgentCreateParams = {
provider: AgentProvider; provider: AgentProvider;
model: string | null; model: string | null;
model_parameters: AgentModelParameters; model_parameters: AgentModelParameters;
conversation_starters?: string[];
} & Pick<Agent, 'agent_ids' | 'end_after_tools' | 'hide_sequential_outputs'>; } & Pick<Agent, 'agent_ids' | 'end_after_tools' | 'hide_sequential_outputs'>;
export type AgentUpdateParams = { export type AgentUpdateParams = {
@@ -242,6 +243,7 @@ export type AgentUpdateParams = {
provider?: AgentProvider; provider?: AgentProvider;
model?: string | null; model?: string | null;
model_parameters?: AgentModelParameters; model_parameters?: AgentModelParameters;
conversation_starters?: string[] | null;
projectIds?: string[]; projectIds?: string[];
removeProjectIds?: string[]; removeProjectIds?: string[];
isCollaborative?: boolean; isCollaborative?: boolean;