Add automatic chat mode with native tool calling support (#5140)

Introduces a new automatic chat mode (now the default) that automatically invokes tools when the provider supports native tool calling. Conditionally shows/hides the @agent command based on whether native tooling is available.

    - Add supportsNativeToolCalling() to AI providers (OpenAI, Anthropic, Azure always support; others opt-in via ENV)
    - Update all locale translations with new mode descriptions
    - Enhance translator to preserve Trans component tags
    - Remove deprecated ability tags UI
This commit is contained in:
Timothy Carambat 2026-03-04 14:34:30 -08:00 committed by GitHub
parent 4cd3c77893
commit 4c69960dca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
47 changed files with 551 additions and 263 deletions

View File

@ -51,6 +51,36 @@ function restorePlaceholders(text, placeholders) {
}); });
} }
/**
* Extract Trans component tags like <italic>, </italic>, <bold>, </bold>, etc.
* These are used by react-i18next Trans component for rich text formatting.
* @param {string} text
* @returns {{ text: string, tags: string[] }}
*/
function extractTransTags(text) {
const tags = [];
// Match opening tags <tagName> and closing tags </tagName>
// Also matches self-closing tags <tagName />
const modifiedText = text.replace(/<\/?([a-zA-Z][a-zA-Z0-9]*)\s*\/?>/g, (match) => {
const index = tags.length;
tags.push(match);
return `__TAG_${index}__`;
});
return { text: modifiedText, tags };
}
/**
* Restore original Trans component tags from tokens.
* @param {string} text
* @param {string[]} tags
* @returns {string}
*/
function restoreTransTags(text, tags) {
return text.replace(/__TAG_(\d+)__/g, (_, index) => {
return tags[parseInt(index, 10)] || `__TAG_${index}__`;
});
}
/** /**
* Validate that all placeholders from source exist in translated text. * Validate that all placeholders from source exist in translated text.
* @param {string} sourceText * @param {string} sourceText
@ -64,6 +94,19 @@ function validatePlaceholders(sourceText, translatedText) {
return { valid: missing.length === 0, missing }; return { valid: missing.length === 0, missing };
} }
/**
* Validate that all Trans component tags from source exist in translated text.
* @param {string} sourceText
* @param {string} translatedText
* @returns {{ valid: boolean, missing: string[] }}
*/
function validateTransTags(sourceText, translatedText) {
const sourceMatches = sourceText.match(/<\/?([a-zA-Z][a-zA-Z0-9]*)\s*\/?>/g) || [];
const translatedMatches = translatedText.match(/<\/?([a-zA-Z][a-zA-Z0-9]*)\s*\/?>/g) || [];
const missing = sourceMatches.filter(t => !translatedMatches.includes(t));
return { valid: missing.length === 0, missing };
}
class Translator { class Translator {
static modelTag = 'translategemma:4b' static modelTag = 'translategemma:4b'
constructor() { constructor() {
@ -87,13 +130,19 @@ class Translator {
console.log(`\x1b[32m[Translator]\x1b[0m ${text}`, ...args); console.log(`\x1b[32m[Translator]\x1b[0m ${text}`, ...args);
} }
buildPrompt(text, sourceLangCode, targetLangCode, hasPlaceholders = false) { buildPrompt(text, sourceLangCode, targetLangCode, { hasPlaceholders = false, hasTags = false } = {}) {
const sourceLanguage = this.getLanguageName(sourceLangCode); const sourceLanguage = this.getLanguageName(sourceLangCode);
const targetLanguage = this.getLanguageName(targetLangCode); const targetLanguage = this.getLanguageName(targetLangCode);
const placeholderInstruction = hasPlaceholders
? `\nIMPORTANT: The text contains placeholders like __PLACEHOLDER_0__, __PLACEHOLDER_1__, etc. You MUST keep these placeholders exactly as they are in the translation - do not translate, modify, or remove them.` let specialInstructions = '';
: ''; if (hasPlaceholders || hasTags) {
return `You are a professional ${sourceLanguage} (${sourceLangCode.toLowerCase()}) to ${targetLanguage} (${targetLangCode.toLowerCase()}) translator. Your goal is to accurately convey the meaning and nuances of the original ${sourceLanguage} text while adhering to ${targetLanguage} grammar, vocabulary, and cultural sensitivities.${placeholderInstruction} const items = [];
if (hasPlaceholders) items.push('__PLACEHOLDER_0__, __PLACEHOLDER_1__');
if (hasTags) items.push('__TAG_0__, __TAG_1__');
specialInstructions = `\nIMPORTANT: The text contains tokens like ${items.join(', ')}, etc. You MUST keep these tokens exactly as they are in the translation - do not translate, modify, or remove them.`;
}
return `You are a professional ${sourceLanguage} (${sourceLangCode.toLowerCase()}) to ${targetLanguage} (${targetLangCode.toLowerCase()}) translator. Your goal is to accurately convey the meaning and nuances of the original ${sourceLanguage} text while adhering to ${targetLanguage} grammar, vocabulary, and cultural sensitivities.${specialInstructions}
Produce only the ${targetLanguage} translation, without any additional explanations or commentary. Please translate the following ${sourceLanguage} text into ${targetLanguage}: Produce only the ${targetLanguage} translation, without any additional explanations or commentary. Please translate the following ${sourceLanguage} text into ${targetLanguage}:
@ -113,11 +162,15 @@ ${text}`
async translate(text, sourceLangCode, targetLangCode) { async translate(text, sourceLangCode, targetLangCode) {
// Extract placeholders like {{variableName}} and replace with tokens // Extract placeholders like {{variableName}} and replace with tokens
const { text: textWithTokens, placeholders } = extractPlaceholders(text); const { text: textWithPlaceholders, placeholders } = extractPlaceholders(text);
const hasPlaceholders = placeholders.length > 0; const hasPlaceholders = placeholders.length > 0;
const prompt = this.buildPrompt(textWithTokens, sourceLangCode, targetLangCode, hasPlaceholders); // Extract Trans component tags like <italic>, </italic>, etc.
const response = await fetch(`http://localhost:11434/api/chat`, { const { text: textWithTokens, tags } = extractTransTags(textWithPlaceholders);
const hasTags = tags.length > 0;
const prompt = this.buildPrompt(textWithTokens, sourceLangCode, targetLangCode, { hasPlaceholders, hasTags });
const response = await fetch(`http://127.0.0.1:11434/api/chat`, {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ body: JSON.stringify({
@ -132,6 +185,22 @@ ${text}`
const data = await response.json(); const data = await response.json();
let translatedText = this.cleanOutputText(data.message.content); let translatedText = this.cleanOutputText(data.message.content);
// Restore Trans component tags first (order matters since tags may contain placeholders)
if (hasTags) {
translatedText = restoreTransTags(translatedText, tags);
// Validate all tags were preserved
const tagValidation = validateTransTags(text, translatedText);
if (!tagValidation.valid) {
console.warn(`Warning: Missing Trans tags in translation: ${tagValidation.missing.join(', ')}`);
for (let i = 0; i < tags.length; i++) {
if (!translatedText.includes(tags[i])) {
console.warn(` Tag ${tags[i]} was lost in translation`);
}
}
}
}
// Restore original placeholders // Restore original placeholders
if (hasPlaceholders) { if (hasPlaceholders) {
translatedText = restorePlaceholders(translatedText, placeholders); translatedText = restorePlaceholders(translatedText, placeholders);

View File

@ -34,14 +34,6 @@ export default function AvailableAgentsButton({ showing, setShowAgents }) {
); );
} }
function AbilityTag({ text }) {
return (
<div className="px-2 bg-theme-action-menu-item-hover text-theme-text-secondary text-xs w-fit rounded-sm">
<p>{text}</p>
</div>
);
}
export function AvailableAgents({ export function AvailableAgents({
showing, showing,
setShowing, setShowing,
@ -109,26 +101,6 @@ export function AvailableAgents({
<b>{t("chat_window.at_agent")}</b> <b>{t("chat_window.at_agent")}</b>
{t("chat_window.default_agent_description")} {t("chat_window.default_agent_description")}
</div> </div>
<div className="flex flex-wrap gap-2 mt-2">
<AbilityTag text="rag-search" />
<AbilityTag text="web-scraping" />
<AbilityTag text="web-browsing" />
<AbilityTag text="save-file-to-browser" />
<AbilityTag text="list-documents" />
<AbilityTag text="summarize-document" />
<AbilityTag text="chart-generation" />
</div>
</div>
</button>
<button
type="button"
disabled={true}
className="w-full rounded-xl flex flex-col justify-start group"
>
<div className="w-full flex-col text-center flex pointer-events-none">
<div className="text-theme-text-secondary text-xs italic">
{t("chat_window.custom_agents_coming_soon")}
</div>
</div> </div>
</button> </button>
</div> </div>

View File

@ -31,6 +31,7 @@ export const PROMPT_INPUT_EVENT = "set_prompt_input";
const MAX_EDIT_STACK_SIZE = 100; const MAX_EDIT_STACK_SIZE = 100;
/** /**
* @param {Workspace} props.workspace - workspace object
* @param {function} props.submit - form submit handler * @param {function} props.submit - form submit handler
* @param {boolean} props.isStreaming - disables input while streaming response * @param {boolean} props.isStreaming - disables input while streaming response
* @param {function} props.sendCommand - handler for slash commands and agent mentions * @param {function} props.sendCommand - handler for slash commands and agent mentions
@ -40,6 +41,7 @@ const MAX_EDIT_STACK_SIZE = 100;
* @param {string} [props.threadSlug] - thread slug for home page context * @param {string} [props.threadSlug] - thread slug for home page context
*/ */
export default function PromptInput({ export default function PromptInput({
workspace = {},
submit, submit,
isStreaming, isStreaming,
sendCommand, sendCommand,
@ -49,6 +51,7 @@ export default function PromptInput({
threadSlug = null, threadSlug = null,
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
const { showAgentCommand = true } = workspace ?? {};
const { isDisabled } = useIsDisabled(); const { isDisabled } = useIsDisabled();
const [promptInput, setPromptInput] = useState(""); const [promptInput, setPromptInput] = useState("");
const { showAgents, setShowAgents } = useAvailableAgents(); const { showAgents, setShowAgents } = useAvailableAgents();
@ -273,13 +276,15 @@ export default function PromptInput({
promptRef={textareaRef} promptRef={textareaRef}
centered={centered} centered={centered}
/> />
<AvailableAgents {showAgentCommand && (
showing={showAgents} <AvailableAgents
setShowing={setShowAgents} showing={showAgents}
sendCommand={sendCommand} setShowing={setShowAgents}
promptRef={textareaRef} sendCommand={sendCommand}
centered={centered} promptRef={textareaRef}
/> centered={centered}
/>
)}
<form <form
onSubmit={handleSubmit} onSubmit={handleSubmit}
className={ className={
@ -325,10 +330,14 @@ export default function PromptInput({
showing={showSlashCommand} showing={showSlashCommand}
setShowSlashCommand={setShowSlashCommand} setShowSlashCommand={setShowSlashCommand}
/> />
<AvailableAgentsButton
showing={showAgents} {showAgentCommand && (
setShowAgents={setShowAgents} <AvailableAgentsButton
/> showing={showAgents}
setShowAgents={setShowAgents}
/>
)}
<TextSizeButton /> <TextSizeButton />
<LLMSelectorAction workspaceSlug={workspaceSlug} /> <LLMSelectorAction workspaceSlug={workspaceSlug} />
</div> </div>

View File

@ -338,6 +338,7 @@ export default function ChatContainer({ workspace, knownHistory = [] }) {
{t("main-page.greeting")} {t("main-page.greeting")}
</h1> </h1>
<PromptInput <PromptInput
workspace={workspace}
submit={handleSubmit} submit={handleSubmit}
isStreaming={loadingResponse} isStreaming={loadingResponse}
sendCommand={sendCommand} sendCommand={sendCommand}
@ -388,6 +389,7 @@ export default function ChatContainer({ workspace, knownHistory = [] }) {
/> />
</MetricsProvider> </MetricsProvider>
<PromptInput <PromptInput
workspace={workspace}
submit={handleSubmit} submit={handleSubmit}
isStreaming={loadingResponse} isStreaming={loadingResponse}
sendCommand={sendCommand} sendCommand={sendCommand}

View File

@ -186,15 +186,18 @@ const TRANSLATIONS = {
title: "وضع المحادثة", title: "وضع المحادثة",
chat: { chat: {
title: "المحادثة", title: "المحادثة",
"desc-start": "سيقدم إجابات حسب المعرفة العامة لنموذج التعلم العميق", description:
and: "and", 'سيوفر إجابات بناءً على المعرفة العامة للنموذج اللغوي، بالإضافة إلى السياق الوثائقي المتاح.\nستحتاج إلى استخدام الأمر "@agent" لاستخدام الأدوات.',
"desc-end": "المستند الذي تم العثور عليه حسب السياق.",
}, },
query: { query: {
title: "استعلام", title: "استعلام",
"desc-start": "سوف تقدم الإجابات", description:
only: "فقط", 'سيوفر الإجابات <b/>فقط<b/> إذا تم العثور على سياق الوثيقة.\nستحتاج إلى استخدام الأمر "@agent" لاستخدام الأدوات.',
"desc-end": "إذا وجد المستند في السياق", },
automatic: {
title: "سيارة",
description:
'سيتم استخدام الأدوات تلقائيًا إذا كان النموذج والمزود يدعمان استدعاء الأدوات الأصلية.\nإذا لم يتم دعم الأدوات الأصلية، فسيتعين عليك استخدام الأمر "@agent" لاستخدام الأدوات.',
}, },
}, },
history: { history: {
@ -691,7 +694,8 @@ const TRANSLATIONS = {
edit_prompt: "اقتراح التحرير", edit_prompt: "اقتراح التحرير",
edit_response: "عدّل الرد", edit_response: "عدّل الرد",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: "- الوكيل الافتراضي لهذا المساحة.", default_agent_description:
"- استخدام الأدوات والبرامج المتاحة لإنجاز المهام.",
custom_agents_coming_soon: "سيصل وكلاء مخصصون قريباً!", custom_agents_coming_soon: "سيصل وكلاء مخصصون قريباً!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: "امسح سجل الدردشة الخاص بك وابدأ محادثة جديدة", preset_reset_description: "امسح سجل الدردشة الخاص بك وابدأ محادثة جديدة",

View File

@ -286,15 +286,18 @@ const TRANSLATIONS = {
title: "Režim chatu", title: "Režim chatu",
chat: { chat: {
title: "Chat", title: "Chat",
"desc-start": "bude poskytovat odpovědi s obecnými znalostmi LLM", description:
and: "a", "budou poskytovat odpovědi založené na obecných znalostech LLM a kontextu dokumentu, který je k dispozici. Pro použití nástrojů budete muset použít příkaz `@agent`.",
"desc-end": "kontext dokumentu, který je nalezen.",
}, },
query: { query: {
title: "Dotaz", title: "Dotaz",
"desc-start": "bude poskytovat odpovědi", description:
only: "pouze", "budou poskytovat odpovědi <b>pouze__, pokud je nalezen kontext dokumentu.</b>Budete muset použít příkaz @agent pro použití nástrojů.",
"desc-end": "pokud je nalezen kontext dokumentu.", },
automatic: {
title: "Auto",
description:
"automaticky použije nástroje, pokud to podporují model a poskytovatel. Pokud není podporováno nativní volání nástrojů, budete muset použít příkaz `@agent` pro použití nástrojů.",
}, },
}, },
history: { history: {
@ -920,7 +923,8 @@ const TRANSLATIONS = {
edit_prompt: "Upravit výzvu", edit_prompt: "Upravit výzvu",
edit_response: "Upravit odpověď", edit_response: "Upravit odpověď",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: " - výchozí agent pro tento pracovní prostor.", default_agent_description:
" využívat nástroje a metodiky (MCP) k plnění úkolů.",
custom_agents_coming_soon: "vlastní agenti přicházejí brzy!", custom_agents_coming_soon: "vlastní agenti přicházejí brzy!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: "Vymazat historii chatu a začít nový chat", preset_reset_description: "Vymazat historii chatu a začít nový chat",

View File

@ -188,15 +188,18 @@ const TRANSLATIONS = {
title: "Chat-tilstand", title: "Chat-tilstand",
chat: { chat: {
title: "Chat", title: "Chat",
"desc-start": "vil give svar baseret på LLM'ens generelle viden", description:
and: "og", "vil give svar baseret på LLM'ens generelle viden og den dokumentkontekst, der findes.\nDu skal bruge kommandoen `@agent` for at bruge værktøjerne.",
"desc-end": "dokumentkontekst der findes.",
}, },
query: { query: {
title: "Forespørgsel", title: "Forespørgsel",
"desc-start": "vil give svar", description:
only: "kun", 'vil kun give svar, hvis dokumentets kontekst er fundet.\nDu skal bruge kommandoen "@agent" for at bruge værktøjerne.',
"desc-end": "hvis dokumentkontekst findes.", },
automatic: {
title: "Bil",
description:
"systemet vil automatisk bruge værktøjer, hvis modellen og leverandøren understøtter direkte kald af værktøjer.<br />Hvis direkte brug af værktøjer ikke understøttes, skal du bruge kommandoen `@agent` for at bruge værktøjerne.",
}, },
}, },
history: { history: {
@ -701,7 +704,8 @@ const TRANSLATIONS = {
edit_prompt: "Redigeringsanmodning", edit_prompt: "Redigeringsanmodning",
edit_response: "Rediger svar", edit_response: "Rediger svar",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: "- standardagenten for dette arbejdsområde.", default_agent_description:
"- udnytte værktøjer og metoder (MCP'er) til at gennemføre opgaver.",
custom_agents_coming_soon: "Specialagenter kommer snart!", custom_agents_coming_soon: "Specialagenter kommer snart!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: preset_reset_description:

View File

@ -280,15 +280,18 @@ const TRANSLATIONS = {
title: "Chat-Modus", title: "Chat-Modus",
chat: { chat: {
title: "Chat", title: "Chat",
"desc-start": "wird Antworten mit dem allgemeinen Wissen des LLM", description:
and: "und", 'wird Antworten basierend auf dem allgemeinen Wissen des LLM und dem im Dokument gefundenen Kontext liefern.\nSie müssen den Befehl "@agent" verwenden, um Tools zu nutzen.',
"desc-end": "gefundenem Dokumentenkontext liefern.",
}, },
query: { query: {
title: "Abfrage", title: "Abfrage",
"desc-start": "wird Antworten", description:
only: "nur", 'wird Antworten <b/>nur dann<b/> bereitstellen, wenn der Kontext des Dokuments gefunden wurde.\nSie müssen den Befehl "@agent" verwenden, um die Tools zu nutzen.',
"desc-end": "liefern, wenn Dokumentenkontext gefunden wird.", },
automatic: {
title: "Auto",
description:
'wird automatisch Werkzeuge verwenden, wenn das Modell und der Anbieter die native Aufruf von Werkzeugen unterstützen.\nWenn die native Verwendung von Werkzeugen nicht unterstützt wird, müssen Sie den Befehl "@agent" verwenden, um Werkzeuge zu nutzen.',
}, },
}, },
history: { history: {
@ -899,7 +902,8 @@ const TRANSLATIONS = {
edit_prompt: "Prompt bearbeiten", edit_prompt: "Prompt bearbeiten",
edit_response: "Antwort bearbeiten", edit_response: "Antwort bearbeiten",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: " Standardagent für diesen Workspace.", default_agent_description:
"- Nutzung von Werkzeugen und Management-Control-Programmen (MCPs) zur Erledigung von Aufgaben.",
custom_agents_coming_soon: "Eigene Agenten bald verfügbar!", custom_agents_coming_soon: "Eigene Agenten bald verfügbar!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: "Chatverlauf löschen und neuen Chat starten", preset_reset_description: "Chatverlauf löschen und neuen Chat starten",

View File

@ -295,17 +295,20 @@ const TRANSLATIONS = {
}, },
mode: { mode: {
title: "Chat mode", title: "Chat mode",
automatic: {
title: "Auto",
description:
"will automatically use tools if the model and provider support native tool calling.<br />If native tooling is not supported, you will need to use the @agent command to use tools.",
},
chat: { chat: {
title: "Chat", title: "Chat",
"desc-start": "will provide answers with the LLM's general knowledge", description:
and: "and", "will provide answers with the LLM's general knowledge <b>and</b> document context that is found.<br />You will need to use the @agent command to use tools.",
"desc-end": "document context that is found.",
}, },
query: { query: {
title: "Query", title: "Query",
"desc-start": "will provide answers", description:
only: "only", "will provide answers <b>only</b> if document context is found.<br />You will need to use the @agent command to use tools.",
"desc-end": "if document context is found.",
}, },
}, },
history: { history: {
@ -961,7 +964,7 @@ const TRANSLATIONS = {
edit_prompt: "Edit prompt", edit_prompt: "Edit prompt",
edit_response: "Edit response", edit_response: "Edit response",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: " - the default agent for this workspace.", default_agent_description: " - leverage tools & MCPs to complete tasks.",
custom_agents_coming_soon: "custom agents are coming soon!", custom_agents_coming_soon: "custom agents are coming soon!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: "Clear your chat history and begin a new chat", preset_reset_description: "Clear your chat history and begin a new chat",

View File

@ -281,16 +281,18 @@ const TRANSLATIONS = {
title: "Modo de chat", title: "Modo de chat",
chat: { chat: {
title: "Chat", title: "Chat",
"desc-start": description:
"proporcionará respuestas con el conocimiento general del LLM", 'proporcionará respuestas basadas en el conocimiento general del LLM y en el contexto del documento que se encuentre.<br />Para utilizar las herramientas, deberá utilizar el comando "@agent".',
and: "y",
"desc-end": "el contexto del documento que se encuentre.",
}, },
query: { query: {
title: "Consulta", title: "Consulta",
"desc-start": "proporcionará respuestas", description:
only: "solo", 'proporcionará respuestas **únicamente** si se encuentra el contexto del documento.\nDeberá utilizar el comando "@agent" para utilizar las herramientas.',
"desc-end": "si se encuentra contexto del documento.", },
automatic: {
title: "Coche",
description:
'utilizará automáticamente las herramientas si el modelo y el proveedor admiten la llamada nativa a herramientas.\nSi no se admite la llamada nativa a herramientas, deberá utilizar el comando "@agent" para utilizar las herramientas.',
}, },
}, },
history: { history: {
@ -909,9 +911,9 @@ const TRANSLATIONS = {
cancel: "Cancelar", cancel: "Cancelar",
edit_prompt: "Editar prompt", edit_prompt: "Editar prompt",
edit_response: "Editar respuesta", edit_response: "Editar respuesta",
at_agent: "@agente", at_agent: "@agent",
default_agent_description: default_agent_description:
" - el agente predeterminado para este espacio de trabajo.", "- Utilizar herramientas y metodologías específicas para completar las tareas.",
custom_agents_coming_soon: "¡los agentes personalizados llegarán pronto!", custom_agents_coming_soon: "¡los agentes personalizados llegarán pronto!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: preset_reset_description:

View File

@ -271,15 +271,18 @@ const TRANSLATIONS = {
title: "Vestlusrežiim", title: "Vestlusrežiim",
chat: { chat: {
title: "Vestlus", title: "Vestlus",
"desc-start": "annab vastuseid LLM-i üldteadmistest", description:
and: "ja", 'teenab vastuseid, kasutades LLM-i üldist teadmist ja leida saanud dokumentide konteksti.\nEt kasutada tööriime, peate kasutama käsku "@agent".',
"desc-end": "leitud dokumendikontekstist.",
}, },
query: { query: {
title: "Päring", title: "Päring",
"desc-start": "annab vastuseid", description:
only: "ainult", "teenab vastuseid <b/> ainult siis, kui dokumenti kontekst on leitav.<br />Kasutamiseks peate kasutama käitu @agent.",
"desc-end": "kui leitakse dokumendikontekst.", },
automatic: {
title: "Automaailm",
description:
'kasutab automaatselt tööriistu, kui mudel ja pakkuja toetavad native tööriistade kasutamist.<br />Kui native tööriistade kasutamine ei toeta, siis peate kasutama käsku "@agent", et tööriiste kasutada.',
}, },
}, },
history: { history: {
@ -858,7 +861,8 @@ const TRANSLATIONS = {
edit_prompt: "Redigeeri päringut", edit_prompt: "Redigeeri päringut",
edit_response: "Redigeeri vastust", edit_response: "Redigeeri vastust",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: " selle tööruumi vaikimisi agent.", default_agent_description:
" kasutada töörimeid ja tegevuste haldamise süsteeme (MCP) ülesannete täitmiseks.",
custom_agents_coming_soon: "kohandatud agendid tulekul!", custom_agents_coming_soon: "kohandatud agendid tulekul!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: "Tühjenda vestlusajalugu ja alusta uut vestlust", preset_reset_description: "Tühjenda vestlusajalugu ja alusta uut vestlust",

View File

@ -187,15 +187,18 @@ const TRANSLATIONS = {
title: "حالت گفتگو", title: "حالت گفتگو",
chat: { chat: {
title: "گفتگو", title: "گفتگو",
"desc-start": "پاسخ‌ها را با دانش عمومی LLM", description:
and: "و", "با استفاده از دانش عمومی مدل زبان بزرگ و همچنین اطلاعات موجود در مستند، پاسخ‌ها را ارائه می‌دهد. برای استفاده از ابزارها، باید از دستور @agent استفاده کنید.",
"desc-end": "محتوای اسناد یافت شده ارائه می‌دهد.",
}, },
query: { query: {
title: "پرس‌وجو", title: "پرس‌وجو",
"desc-start": "پاسخ‌ها را", description:
only: "فقط", 'پاسخ‌ها را تنها در صورتی ارائه می‌دهد که زمینه سند مشخص باشد.\nبرای استفاده از ابزارها، باید از دستور "@agent" استفاده کنید.',
"desc-end": "در صورت یافتن محتوای اسناد ارائه می‌دهد.", },
automatic: {
title: "خودرو",
description:
"در صورتی که مدل و ارائه دهنده از فراخوانی ابزار به صورت داخلی پشتیبانی کنند، ابزارها به طور خودکار استفاده خواهند شد.\nاگر فراخوانی ابزار به صورت داخلی پشتیبانی نشود، شما باید از دستور @agent برای استفاده از ابزارها استفاده کنید.",
}, },
}, },
history: { history: {
@ -698,7 +701,8 @@ const TRANSLATIONS = {
edit_prompt: "لطفاً دستور ویرایش را ارائه دهید.", edit_prompt: "لطفاً دستور ویرایش را ارائه دهید.",
edit_response: "لطفا پاسخ را ویرایش کنید.", edit_response: "لطفا پاسخ را ویرایش کنید.",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: "- عامل پیش‌فرض برای این فضای کاری.", default_agent_description:
"- استفاده از ابزارها و سیستم‌های مدیریت کار (MCP) برای انجام وظایف.",
custom_agents_coming_soon: "نمایندگان ویژه در حال آمدن هستند!", custom_agents_coming_soon: "نمایندگان ویژه در حال آمدن هستند!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: "حذف تاریخچه چت خود و شروع یک چت جدید", preset_reset_description: "حذف تاریخچه چت خود و شروع یک چت جدید",

View File

@ -189,16 +189,18 @@ const TRANSLATIONS = {
title: "Mode de chat", title: "Mode de chat",
chat: { chat: {
title: "Chat", title: "Chat",
"desc-start": description:
"fournira des réponses avec les connaissances générales du LLM", 'fournira des réponses basées sur les connaissances générales du LLM et sur le contexte des documents trouvés.\nVous devrez utiliser la commande "@agent" pour utiliser les outils.',
and: "et",
"desc-end": "le contexte du document trouvé.",
}, },
query: { query: {
title: "Requête", title: "Requête",
"desc-start": "fournira des réponses", description:
only: "uniquement", "fournira des réponses <b/>uniquement<b/> si le contexte du document est trouvé.\nVous devrez utiliser la commande @agent pour utiliser les outils.",
"desc-end": "si un contexte de document est trouvé.", },
automatic: {
title: "Voiture",
description:
"il utilisera automatiquement les outils si le modèle et le fournisseur prennent en charge l'appel de fonctions natives.\nSi l'appel de fonctions natives n'est pas pris en charge, vous devrez utiliser la commande \"@agent\" pour utiliser les outils.",
}, },
}, },
history: { history: {
@ -702,7 +704,8 @@ const TRANSLATIONS = {
edit_prompt: "Modifier le prompt", edit_prompt: "Modifier le prompt",
edit_response: "Modifier la réponse", edit_response: "Modifier la réponse",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: "l'agent par défaut de cet espace de travail", default_agent_description:
"- utiliser des outils et des méthodes de gestion de projet pour mener à bien les tâches.",
custom_agents_coming_soon: "Agents personnalisés bientôt disponibles", custom_agents_coming_soon: "Agents personnalisés bientôt disponibles",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: preset_reset_description:

View File

@ -271,15 +271,18 @@ const TRANSLATIONS = {
title: "מצב צ'אט", title: "מצב צ'אט",
chat: { chat: {
title: "צ'אט", title: "צ'אט",
"desc-start": "יספק תשובות עם הידע הכללי של מודל השפה", description:
and: "וכן", 'יוכל לספק תשובות המבוססות על הידע הכללי של ה-LLM וכן על ההקשר הרלוונטי המצוי בתיעוד.\nתצטרכו להשתמש בפקודה "@agent" כדי להשתמש בכלי.',
"desc-end": "מהקשר המסמכים שנמצא.",
}, },
query: { query: {
title: "שאילתה", title: "שאילתה",
"desc-start": "יספק תשובות", description:
only: "רק", "יוכל לספק תשובות <b/>רק אם הקשר של המסמך נמצא.<br />תצטרכו להשתמש בפקודה @agent כדי להשתמש בכלי.",
"desc-end": "אם נמצא הקשר במסמכים.", },
automatic: {
title: "רכב",
description:
'הכלי ישתמש באופן אוטומטי בכלים אם המודל והספק תומכים בהם.\nאם אין תמיכה בכלים מקומיים, תצטרכו להשתמש בפקודה "@agent" כדי להשתמש בכלים.',
}, },
}, },
history: { history: {
@ -865,7 +868,8 @@ const TRANSLATIONS = {
edit_prompt: "ערוך הנחיה", edit_prompt: "ערוך הנחיה",
edit_response: "ערוך תגובה", edit_response: "ערוך תגובה",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: " - סוכן ברירת המחדל עבור סביבת עבודה זו.", default_agent_description:
"- שימוש בכלים ובכלים מיוחדים כדי להשלים משימות.",
custom_agents_coming_soon: "סוכנים מותאמים אישית יגיעו בקרוב!", custom_agents_coming_soon: "סוכנים מותאמים אישית יגיעו בקרוב!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: "נקה את היסטוריית הצ'אט שלך והתחל צ'אט חדש", preset_reset_description: "נקה את היסטוריית הצ'אט שלך והתחל צ'אט חדש",

View File

@ -190,15 +190,18 @@ const TRANSLATIONS = {
title: "Modalità chat", title: "Modalità chat",
chat: { chat: {
title: "Chat", title: "Chat",
"desc-start": "fornirà risposte con la conoscenza generale dell'LLM", description:
and: "e", 'fornirà risposte basate sulla conoscenza generale dell\'LLM e sul contesto del documento rilevante.\nPer utilizzare gli strumenti, sarà necessario utilizzare il comando "@agent".',
"desc-end": "contesto documentale associato.",
}, },
query: { query: {
title: "Query", title: "Query",
"desc-start": "fornirà risposte", description:
only: "solo", 'fornirà risposte solo se il contesto del documento viene identificato.\nPer utilizzare gli strumenti, sarà necessario utilizzare il comando "@agent".',
"desc-end": "se sarà presente un contesto documentale", },
automatic: {
title: "Auto",
description:
'utilizzerà automaticamente gli strumenti se il modello e il fornitore supportano le chiamate native agli strumenti.\nSe le chiamate native agli strumenti non sono supportate, sarà necessario utilizzare il comando "@agent" per utilizzare gli strumenti.',
}, },
}, },
history: { history: {
@ -708,7 +711,7 @@ const TRANSLATIONS = {
edit_response: "Modifica la risposta", edit_response: "Modifica la risposta",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: default_agent_description:
"- l'agente predefinito per questo spazio di lavoro.", "- utilizzare strumenti e risorse gestite centralmente per completare i compiti.",
custom_agents_coming_soon: "Agenti personalizzati in arrivo a breve!", custom_agents_coming_soon: "Agenti personalizzati in arrivo a breve!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: preset_reset_description:

View File

@ -187,15 +187,18 @@ const TRANSLATIONS = {
title: "チャットモード", title: "チャットモード",
chat: { chat: {
title: "チャット", title: "チャット",
"desc-start": "LLMの一般知識で回答します", description:
and: "および", "LLMの一般的な知識と、利用可能なドキュメントの文脈に基づいて回答を提供します。ツールを使用するには、`@agent`コマンドを使用する必要があります。",
"desc-end": "見つかったドキュメントコンテキストを使用します。",
}, },
query: { query: {
title: "クエリ", title: "クエリ",
"desc-start": "回答を提供します", description:
only: "のみ", '回答は、ドキュメントの文脈が特定された場合にのみ提供されます。\nツールを使用するには、"@agent" コマンドを使用する必要があります。',
"desc-end": "ドキュメントコンテキストが見つかった場合のみ。", },
automatic: {
title: "自動車",
description:
"ネイティブなツール呼び出しをサポートしている場合、モデルとプロバイダーが自動的にツールを使用します。\nネイティブなツール呼び出しがサポートされていない場合は、@agentコマンドを使用してツールを使用する必要があります。",
}, },
}, },
history: { history: {
@ -691,7 +694,8 @@ const TRANSLATIONS = {
edit_prompt: "編集のヒント", edit_prompt: "編集のヒント",
edit_response: "編集内容を保存します。", edit_response: "編集内容を保存します。",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: "- このワークスペースのデフォルトエージェント。", default_agent_description:
"- ツールやマニュアルを活用して、タスクを完了する。",
custom_agents_coming_soon: "カスタムエージェントは近日公開予定です。", custom_agents_coming_soon: "カスタムエージェントは近日公開予定です。",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: preset_reset_description:

View File

@ -272,15 +272,18 @@ const TRANSLATIONS = {
title: "채팅 모드", title: "채팅 모드",
chat: { chat: {
title: "채팅", title: "채팅",
"desc-start": "문서 내용을 찾습니다.", description:
and: "그리고", "LLM의 일반적인 지식과 함께, 문맥에 맞는 답변을 제공합니다. 도구를 사용하려면 @agent 명령어를 사용해야 합니다.",
"desc-end": "LLM의 일반 지식을 같이 사용하여 답변을 제공합니다",
}, },
query: { query: {
title: "쿼리", title: "쿼리",
"desc-start": "문서 컨텍스트를 찾을 ", description:
only: "때만", "답변은 문서의 맥락이 발견될 경우에만 제공됩니다. 도구를 사용하려면 `@agent` 명령어를 사용해야 합니다.",
"desc-end": "답변을 제공합니다.", },
automatic: {
title: "자동",
description:
"모델과 제공업체가 네이티브 도구 호출을 지원하는 경우, 자동으로 도구를 사용합니다.\n\n네이티브 도구 호출이 지원되지 않는 경우, @agent 명령어를 사용하여 도구를 사용해야 합니다.",
}, },
}, },
history: { history: {
@ -874,7 +877,8 @@ const TRANSLATIONS = {
edit_prompt: "프롬프트 수정", edit_prompt: "프롬프트 수정",
edit_response: "응답 수정", edit_response: "응답 수정",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: " - 이 워크스페이스의 기본 에이전트입니다.", default_agent_description:
"- 다양한 도구 및 MCP(관리형 서비스)를 활용하여 작업을 완료합니다.",
custom_agents_coming_soon: "커스텀 에이전트 기능이 곧 제공됩니다!", custom_agents_coming_soon: "커스텀 에이전트 기능이 곧 제공됩니다!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: "채팅 기록을 초기화하고 새 채팅을 시작합니다", preset_reset_description: "채팅 기록을 초기화하고 새 채팅을 시작합니다",

View File

@ -276,15 +276,18 @@ const TRANSLATIONS = {
title: "Sarunas režīms", title: "Sarunas režīms",
chat: { chat: {
title: "Saruna", title: "Saruna",
"desc-start": "sniegs atbildes ar LLM vispārējām zināšanām", description:
and: "un", 'sniedz atbildes, izmantojot LLM (liels valodas modelis) vispārējo zināšanu un atrastos dokumentu kontekstu.\nLai izmantotu rīkus, jums būs jāizmantojat komanda "@agent".',
"desc-end": "dokumentu kontekstu, kas tiek atrasts.",
}, },
query: { query: {
title: "Vaicājums", title: "Vaicājums",
"desc-start": "sniegs atbildes", description:
only: "tikai", 'sniedz atbildes tikai, ja dokumenta konteksts ir atrasts.<br />Lai izmantotu rīkus, jums jāizmantojat komandu "@agent".',
"desc-end": "ja tiek atrasts dokumentu konteksts.", },
automatic: {
title: "Automobiļs",
description:
'automātiski izmantos rīkus, ja modelis un sniedzējs atbalsta vietējo rīku izkļaušanu.<br />Ja vietējā rīku izkļaušana nav atbalstīta, jums būs jāizmantojat komanda "@agent", lai izmantotu rīkus.',
}, },
}, },
history: { history: {
@ -891,7 +894,8 @@ const TRANSLATIONS = {
edit_prompt: "Ieslēgt", edit_prompt: "Ieslēgt",
edit_response: "Rediģēt atbildi", edit_response: "Rediģēt atbildi",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: "- noklusējuma aģents šim darba telpai.", default_agent_description:
" izmantot rīkus un MCP (personas darba plānus) lai pabeigtu uzdevumus.",
custom_agents_coming_soon: custom_agents_coming_soon:
"Nedaudz drīzumā būs pieejami individuāli pakalpojumi!", "Nedaudz drīzumā būs pieejami individuāli pakalpojumi!",
slash_reset: "/reset", slash_reset: "/reset",

View File

@ -188,15 +188,18 @@ const TRANSLATIONS = {
title: "Chatmodus", title: "Chatmodus",
chat: { chat: {
title: "Chat", title: "Chat",
"desc-start": "zal antwoorden geven met de algemene kennis van de LLM", description:
and: "en", "zal antwoorden genereren met behulp van de algemene kennis van het LLM en de documentcontext die beschikbaar is.<br />U moet het commando `@agent` gebruiken om tools te gebruiken.",
"desc-end": "documentcontext die wordt gevonden.",
}, },
query: { query: {
title: "Query", title: "Query",
"desc-start": "zal antwoorden geven", description:
only: "alleen", "zal antwoorden geven <b/>alleen</b/> als de context van het document wordt gevonden.\nU moet het commando `@agent` gebruiken om de tools te gebruiken.",
"desc-end": "als documentcontext wordt gevonden.", },
automatic: {
title: "Auto",
description:
"zal automatisch tools gebruiken als het model en de provider native tool-aanroepen ondersteunen.<br />Als native tooling niet wordt ondersteund, moet u het `@agent`-commando gebruiken om tools te gebruiken.",
}, },
}, },
history: { history: {
@ -702,7 +705,8 @@ const TRANSLATIONS = {
edit_prompt: "Prompt bewerken", edit_prompt: "Prompt bewerken",
edit_response: "Reactie bewerken", edit_response: "Reactie bewerken",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: " - de standaardagent voor deze werkruimte.", default_agent_description:
"- gebruik van tools en methoden om taken te voltooien.",
custom_agents_coming_soon: "Aangepaste agenten komen binnenkort!", custom_agents_coming_soon: "Aangepaste agenten komen binnenkort!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: preset_reset_description:

View File

@ -278,16 +278,18 @@ const TRANSLATIONS = {
title: "Tryb czatu", title: "Tryb czatu",
chat: { chat: {
title: "Czat", title: "Czat",
"desc-start": "dostarczy odpowiedzi na podstawie wiedzy ogólnej LLM", description:
and: "oraz", "zapewnią odpowiedzi oparte na ogólnym zasobie wiedzy LLM oraz kontekście dokumentu, w którym ta wiedza znajduje się. <br /> Będziesz musiał użyć komendy `@agent` w celu korzystania z narzędzi.",
"desc-end": " znalezionym kontekście (dokumenty, źródła danych)",
}, },
query: { query: {
title: "Zapytanie (wyszukiwanie)", title: "Zapytanie (wyszukiwanie)",
"desc-start": "dostarczy odpowiedzi", description:
only: "tylko", "będzie dostarczać odpowiedzi <b>tylko</b>, jeśli zostanie zidentyfikowany kontekst dokumentu.<br />Będziesz musiał użyć polecenia `@agent` w celu korzystania z narzędzi.",
"desc-end": },
"na podstawie znalezionego kontekstu (dokumenty, źródła danych) - w przeciwnym razie odmówi odpowiedzi.", automatic: {
title: "Samochód",
description:
"automatycznie będzie korzystać z narzędzi, jeśli model i dostawca obsługują natywne wywoływanie narzędzi. W przypadku, gdy natywne wywoływanie narzędzi nie jest obsługiwane, konieczne będzie użycie komendy `@agent` w celu korzystania z narzędzi.",
}, },
}, },
history: { history: {
@ -893,7 +895,8 @@ const TRANSLATIONS = {
edit_prompt: "Edytuj prompt", edit_prompt: "Edytuj prompt",
edit_response: "Edytuj odpowiedź", edit_response: "Edytuj odpowiedź",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: " - domyślny agent dla tego obszaru roboczego.", default_agent_description:
"- wykorzystywać dostępne narzędzia i zasoby, aby wykonywać zadania.",
custom_agents_coming_soon: "niestandardowi agenci już wkrótce!", custom_agents_coming_soon: "niestandardowi agenci już wkrótce!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: "Wyczyść historię czatu i rozpocznij nowy czat", preset_reset_description: "Wyczyść historię czatu i rozpocznij nowy czat",

View File

@ -274,15 +274,18 @@ const TRANSLATIONS = {
title: "Modo de Chat", title: "Modo de Chat",
chat: { chat: {
title: "Chat", title: "Chat",
"desc-start": "fornecerá respostas com conhecimento geral do LLM", description:
and: "e", 'fornecerá respostas com base no conhecimento geral do LLM e no contexto do documento encontrado.\nVocê precisará usar o comando "@agent" para utilizar as ferramentas.',
"desc-end": "contexto dos documentos encontrados.",
}, },
query: { query: {
title: "Consulta", title: "Consulta",
"desc-start": "fornecerá respostas", description:
only: "apenas", "fornecerá respostas <b/>apenas quando o contexto do documento for encontrado.<br />Você precisará usar o comando @agent para utilizar as ferramentas.",
"desc-end": "se contexto for encontrado nos documentos.", },
automatic: {
title: "Automóvel",
description:
'utilizará automaticamente as ferramentas, caso o modelo e o provedor suportem a chamada nativa de ferramentas.<br />Se a chamada nativa de ferramentas não for suportada, você precisará usar o comando "@agent" para utilizar as ferramentas.',
}, },
}, },
history: { history: {
@ -871,7 +874,8 @@ const TRANSLATIONS = {
edit_prompt: "Editar prompt", edit_prompt: "Editar prompt",
edit_response: "Editar resposta", edit_response: "Editar resposta",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: " - o agente padrão deste workspace.", default_agent_description:
"- utilizar ferramentas e processos de gerenciamento de projetos para concluir tarefas.",
custom_agents_coming_soon: "mais agentes personalizados em breve!", custom_agents_coming_soon: "mais agentes personalizados em breve!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: "Limpa o histórico do seu chat e inicia um novo", preset_reset_description: "Limpa o histórico do seu chat e inicia um novo",

View File

@ -280,16 +280,18 @@ const TRANSLATIONS = {
title: "Mod chat", title: "Mod chat",
chat: { chat: {
title: "Chat", title: "Chat",
"desc-start": description:
"oferă răspunsuri bazate pe cunoștințele generale ale LLM-ului", 'va oferi răspunsuri bazate pe cunoștințele generale ale modelului LLM și pe contextul documentului, dacă acesta este disponibil.<br />Va trebui să utilizați comanda "@agent" pentru a utiliza instrumentele.',
and: "și",
"desc-end": "context document care este găsit.",
}, },
query: { query: {
title: "Interogare", title: "Interogare",
"desc-start": "oferă răspunsuri", description:
only: "doar", "va oferi răspunsuri doar dacă contextul documentului este găsit.<br />Veți avea nevoie să utilizați comanda @agent pentru a utiliza instrumentele.",
"desc-end": "dacă contextul documentului este găsit.", },
automatic: {
title: "Mașină",
description:
'va utiliza automat instrumentele, dacă modelul și furnizorul suportă apelarea nativă a instrumentelor. Dacă apelarea nativă a instrumentelor nu este suportată, va trebui să utilizați comanda "@agent" pentru a utiliza instrumentele.',
}, },
}, },
history: { history: {
@ -627,7 +629,7 @@ const TRANSLATIONS = {
edit_response: "Editează răspuns", edit_response: "Editează răspuns",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: default_agent_description:
" - agentul implicit pentru acest spațiu de lucru.", "- utiliza instrumente și resurse specifice pentru a finaliza sarcinile.",
custom_agents_coming_soon: "agenții personalizați vin în curând!", custom_agents_coming_soon: "agenții personalizați vin în curând!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: preset_reset_description:

View File

@ -188,15 +188,18 @@ const TRANSLATIONS = {
title: "Режим чата", title: "Режим чата",
chat: { chat: {
title: "Чат", title: "Чат",
"desc-start": "будет предоставлять ответы с общей информацией LLM", description:
and: "и", "будет предоставлять ответы, основанные на общих знаниях LLM и на контексте документа, который был найден.\nДля использования инструментов необходимо использовать команду `@agent`.",
"desc-end": "найденный контекст документов.",
}, },
query: { query: {
title: "Запрос", title: "Запрос",
"desc-start": "будет предоставлять ответы", description:
only: "только", "будет предоставлять ответы <b/>только</b/> в случае, если будет найден контекст документа.\nДля использования инструментов вам необходимо использовать команду @agent.",
"desc-end": "если найден контекст документов.", },
automatic: {
title: "Авто",
description:
"автоматически будет использовать инструменты, если модель и провайдер поддерживают вызов инструментов напрямую.\nЕсли прямой вызов инструментов не поддерживается, вам потребуется использовать команду `@agent` для использования инструментов.",
}, },
}, },
history: { history: {
@ -700,7 +703,7 @@ const TRANSLATIONS = {
edit_response: "Отредактируйте ответ", edit_response: "Отредактируйте ответ",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: default_agent_description:
"- это основной агент для данного рабочего пространства.", " использовать инструменты и средства управления проектами для выполнения задач.",
custom_agents_coming_soon: "Скоро появятся индивидуальные агенты!", custom_agents_coming_soon: "Скоро появятся индивидуальные агенты!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: "Очистите историю чата и начните новый чат", preset_reset_description: "Очистите историю чата и начните новый чат",

View File

@ -188,15 +188,18 @@ const TRANSLATIONS = {
title: "Sohbet Modu", title: "Sohbet Modu",
chat: { chat: {
title: "Sohbet", title: "Sohbet",
"desc-start": "LLM'nin genel bilgisiyle yanıtlar sunar", description:
and: "ve", 'LLM\'nin genel bilgisi ve bulunan doküman bağlamı sayesinde sorulara cevaplar verecektir. Araçları kullanmak için "@agent" komutunu kullanmanız gerekecektir.',
"desc-end": "bulunan belge bağlamını ekler.",
}, },
query: { query: {
title: "Sorgu", title: "Sorgu",
"desc-start": "yanıtları", description:
only: "sadece", "Cevapları yalnızca, belgelerin bağlamı bulunduğunda sağlayacaktır. Araçları kullanmak için @agent komutunu kullanmanız gerekecektir.",
"desc-end": "belge bağlamı bulunduğunda sunar.", },
automatic: {
title: "Otomobil",
description:
'Eğer model ve sağlayıcı, yerel araç çağırmayı destekliyorsa, araçlar otomatik olarak kullanılacaktır.\nEğer yerel araç kullanımı desteklenmiyorsa, araçları kullanmak için "@agent" komutunu kullanmanız gerekecektir.',
}, },
}, },
history: { history: {
@ -696,7 +699,8 @@ const TRANSLATIONS = {
edit_prompt: "Promptu düzenle", edit_prompt: "Promptu düzenle",
edit_response: "Yanıtı düzenle", edit_response: "Yanıtı düzenle",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: " - bu çalışma alanının varsayılan ajanı.", default_agent_description:
"- Görevleri tamamlamak için araçları ve MCP'leri kullanmak.",
custom_agents_coming_soon: "özel ajanlar yakında!", custom_agents_coming_soon: "özel ajanlar yakında!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: preset_reset_description:

View File

@ -188,15 +188,18 @@ const TRANSLATIONS = {
title: "Chế độ trò chuyện", title: "Chế độ trò chuyện",
chat: { chat: {
title: "Trò chuyện", title: "Trò chuyện",
"desc-start": "sẽ cung cấp câu trả lời với kiến thức chung của LLM", description:
and: "và", 'sẽ cung cấp câu trả lời dựa trên kiến thức chung của LLM và thông tin từ tài liệu được tìm thấy. Bạn cần sử dụng lệnh "@agent" để sử dụng các công cụ.',
"desc-end": "ngữ cảnh tài liệu được tìm thấy.",
}, },
query: { query: {
title: "Truy vấn", title: "Truy vấn",
"desc-start": "sẽ cung cấp câu trả lời", description:
only: "chỉ", "sẽ cung cấp câu trả lời <b/>chỉ khi<b/> thông tin trong tài liệu được tìm thấy.<br />Bạn cần sử dụng lệnh @agent để sử dụng các công cụ.",
"desc-end": "khi tìm thấy ngữ cảnh tài liệu.", },
automatic: {
title: "Tự động",
description:
"hệ thống sẽ tự động sử dụng các công cụ nếu mô hình và nhà cung cấp hỗ trợ gọi công cụ gốc. Nếu không hỗ trợ công cụ gốc, bạn sẽ cần sử dụng lệnh `@agent` để sử dụng các công cụ.",
}, },
}, },
history: { history: {
@ -694,7 +697,8 @@ const TRANSLATIONS = {
edit_prompt: "Chỉnh sửa prompt", edit_prompt: "Chỉnh sửa prompt",
edit_response: "Chỉnh sửa phản hồi", edit_response: "Chỉnh sửa phản hồi",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: " - agent mặc định cho không gian làm việc này.", default_agent_description:
"- Sử dụng các công cụ và quy trình quản lý dự án (MCP) để hoàn thành công việc.",
custom_agents_coming_soon: "agent tùy chỉnh sắp ra mắt!", custom_agents_coming_soon: "agent tùy chỉnh sắp ra mắt!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: preset_reset_description:

View File

@ -266,15 +266,18 @@ const TRANSLATIONS = {
title: "聊天模式", title: "聊天模式",
chat: { chat: {
title: "聊天", title: "聊天",
"desc-start": "将提供 LLM 的一般知识", description:
and: "和", "将提供基于LLM的通用知识和文档上下文信息以便给出答案。\n您需要使用 `@agent` 命令来使用工具。",
"desc-end": "找到的文档上下文的答案。",
}, },
query: { query: {
title: "查询", title: "查询",
"desc-start": "将会提供答案", description:
only: "仅当", "只会提供答案,前提是能够找到文档的上下文。<br />您需要使用 `@agent` 命令来使用工具。",
"desc-end": "找到文档上下文时。", },
automatic: {
title: "汽车",
description:
"如果模型和提供商支持原生工具调用,则会自动使用这些工具。<br />如果不支持原生工具调用,您需要使用 `@agent` 命令来使用工具。",
}, },
}, },
history: { history: {
@ -833,7 +836,7 @@ const TRANSLATIONS = {
edit_prompt: "编辑问题", edit_prompt: "编辑问题",
edit_response: "编辑回应", edit_response: "编辑回应",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: " - 此工作区的预设代理。", default_agent_description: "- 利用工具和管理控制平台MCP来完成任务。",
custom_agents_coming_soon: "自定义代理功能即将推出!", custom_agents_coming_soon: "自定义代理功能即将推出!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: "清除聊天纪录并开始新的聊天", preset_reset_description: "清除聊天纪录并开始新的聊天",

View File

@ -179,15 +179,18 @@ const TRANSLATIONS = {
title: "對話模式", title: "對話模式",
chat: { chat: {
title: "對話", title: "對話",
"desc-start": "將會利用 LLM 的一般知識", description:
and: "和", "將提供利用 LLM 的一般知識以及從文件中提取到的資訊來提供答案。<br />您需要使用 `@agent` 命令來使用工具。",
"desc-end": "找到的文件內容來提供答案。",
}, },
query: { query: {
title: "查詢", title: "查詢",
"desc-start": "將", description:
only: "僅", "僅在找到文件內容時,系統才會提供答案。<br />您需要使用 `@agent` 命令來使用工具。",
"desc-end": "在找到文件內容時提供答案。", },
automatic: {
title: "自動",
description:
"如果模型和供應商都支援原生工具呼叫,系統將自動使用這些工具。<br />如果原生工具呼叫功能未支援,您需要使用 `@agent` 命令來使用工具。",
}, },
}, },
history: { history: {
@ -655,7 +658,7 @@ const TRANSLATIONS = {
edit_prompt: "編輯問題", edit_prompt: "編輯問題",
edit_response: "編輯回應", edit_response: "編輯回應",
at_agent: "@agent", at_agent: "@agent",
default_agent_description: " - 此工作區的預設代理。", default_agent_description: "- 運用工具和專案管理流程,以完成任務。",
custom_agents_coming_soon: "自訂代理功能即將推出!", custom_agents_coming_soon: "自訂代理功能即將推出!",
slash_reset: "/reset", slash_reset: "/reset",
preset_reset_description: "清除聊天紀錄並開始新的聊天", preset_reset_description: "清除聊天紀錄並開始新的聊天",

View File

@ -573,6 +573,27 @@ const Workspace = {
return response; return response;
}, },
/**
* Checks if the agent command is available for a workspace
* by checking if the workspace's agent provider supports native tool calling.
*
* This can be model specific or enabled via ENV flag.
* @param {string} slug - workspace slug
* @returns {Promise<{showAgentCommand: boolean}>}
*/
agentCommandAvailable: async function (slug = null) {
if (!slug) return { showAgentCommand: true };
return await fetch(
`${API_BASE}/workspace/${slug}/is-agent-command-available`,
{ headers: baseHeaders() }
)
.then((res) => res.json())
.catch((e) => {
console.error(e);
return { showAgentCommand: true };
});
},
threads: WorkspaceThread, threads: WorkspaceThread,
}; };

View File

@ -61,11 +61,13 @@ export default function Home() {
async function init() { async function init() {
const ws = await getTargetWorkspace(); const ws = await getTargetWorkspace();
if (ws) { if (ws) {
const [suggestedMessages, pfpUrl] = await Promise.all([ const [suggestedMessages, pfpUrl, { showAgentCommand }] =
Workspace.getSuggestedMessages(ws.slug), await Promise.all([
Workspace.fetchPfp(ws.slug), Workspace.getSuggestedMessages(ws.slug),
]); Workspace.fetchPfp(ws.slug),
setWorkspace({ ...ws, suggestedMessages, pfpUrl }); Workspace.agentCommandAvailable(ws.slug),
]);
setWorkspace({ ...ws, suggestedMessages, pfpUrl, showAgentCommand });
} }
setWorkspaceLoading(false); setWorkspaceLoading(false);
} }
@ -278,6 +280,7 @@ function HomeContent({ workspace, setWorkspace, threadSlug, setThreadSlug }) {
{t("main-page.greeting")} {t("main-page.greeting")}
</h1> </h1>
<PromptInput <PromptInput
workspace={workspace}
submit={handleSubmit} submit={handleSubmit}
isStreaming={loading} isStreaming={loading}
sendCommand={sendCommand} sendCommand={sendCommand}

View File

@ -30,12 +30,17 @@ function ShowWorkspaceChat() {
const _workspace = await Workspace.bySlug(slug); const _workspace = await Workspace.bySlug(slug);
if (!_workspace) return setLoading(false); if (!_workspace) return setLoading(false);
const suggestedMessages = await Workspace.getSuggestedMessages(slug); const [suggestedMessages, pfpUrl, { showAgentCommand }] =
const pfpUrl = await Workspace.fetchPfp(slug); await Promise.all([
Workspace.getSuggestedMessages(slug),
Workspace.fetchPfp(slug),
Workspace.agentCommandAvailable(slug),
]);
setWorkspace({ setWorkspace({
..._workspace, ..._workspace,
suggestedMessages, suggestedMessages,
pfpUrl, pfpUrl,
showAgentCommand,
}); });
setLoading(false); setLoading(false);
localStorage.setItem( localStorage.setItem(

View File

@ -1,7 +1,8 @@
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { Trans, useTranslation } from "react-i18next";
export default function ChatModeSelection({ workspace, setHasChanges }) { export default function ChatModeSelection({ workspace, setHasChanges }) {
const [chatMode, setChatMode] = useState(workspace?.chatMode || "chat"); const [chatMode, setChatMode] = useState(workspace?.chatMode || "automatic");
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<div> <div>
@ -14,6 +15,17 @@ export default function ChatModeSelection({ workspace, setHasChanges }) {
<div className="flex flex-col gap-y-1 mt-2"> <div className="flex flex-col gap-y-1 mt-2">
<div className="w-fit flex gap-x-1 items-center p-1 rounded-lg bg-theme-settings-input-bg "> <div className="w-fit flex gap-x-1 items-center p-1 rounded-lg bg-theme-settings-input-bg ">
<input type="hidden" name="chatMode" value={chatMode} /> <input type="hidden" name="chatMode" value={chatMode} />
<button
type="button"
disabled={chatMode === "automatic"}
onClick={() => {
setChatMode("automatic");
setHasChanges(true);
}}
className="transition-bg duration-200 px-6 py-1 text-md text-white/60 disabled:text-white bg-transparent disabled:bg-[#687280] rounded-md hover:bg-white/10"
>
{t("chat.mode.automatic.title")}
</button>
<button <button
type="button" type="button"
disabled={chatMode === "chat"} disabled={chatMode === "chat"}
@ -21,7 +33,7 @@ export default function ChatModeSelection({ workspace, setHasChanges }) {
setChatMode("chat"); setChatMode("chat");
setHasChanges(true); setHasChanges(true);
}} }}
className="transition-bg duration-200 px-6 py-1 text-md text-white/60 disabled:text-white bg-transparent disabled:bg-[#687280] rounded-md" className="transition-bg duration-200 px-6 py-1 text-md text-white/60 disabled:text-white bg-transparent disabled:bg-[#687280] rounded-md hover:bg-white/10 light:hover:bg-black/10"
> >
{t("chat.mode.chat.title")} {t("chat.mode.chat.title")}
</button> </button>
@ -32,29 +44,31 @@ export default function ChatModeSelection({ workspace, setHasChanges }) {
setChatMode("query"); setChatMode("query");
setHasChanges(true); setHasChanges(true);
}} }}
className="transition-bg duration-200 px-6 py-1 text-md text-white/60 disabled:text-white bg-transparent disabled:bg-[#687280] rounded-md" className="transition-bg duration-200 px-6 py-1 text-md text-white/60 disabled:text-white bg-transparent disabled:bg-[#687280] rounded-md hover:bg-white/10 light:hover:bg-black/10"
> >
{t("chat.mode.query.title")} {t("chat.mode.query.title")}
</button> </button>
</div> </div>
<p className="text-sm text-white/60"> <ChatModeExplanation chatMode={chatMode} />
{chatMode === "chat" ? (
<>
<b>{t("chat.mode.chat.title")}</b>{" "}
{t("chat.mode.chat.desc-start")}{" "}
<i className="font-semibold">{t("chat.mode.chat.and")}</i>{" "}
{t("chat.mode.chat.desc-end")}
</>
) : (
<>
<b>{t("chat.mode.query.title")}</b>{" "}
{t("chat.mode.query.desc-start")}{" "}
<i className="font-semibold">{t("chat.mode.query.only")}</i>{" "}
{t("chat.mode.query.desc-end")}
</>
)}
</p>
</div> </div>
</div> </div>
); );
} }
/**
* A component that displays the explanation for a given chat mode.
* @param {'automatic' | 'chat' | 'query'} chatMode - The chat mode to display the explanation for.
* @returns {JSX.Element} The component to display the explanation for the given chat mode.
*/
function ChatModeExplanation({ chatMode = "chat" }) {
const { t } = useTranslation();
return (
<p className="text-sm text-white/60">
<b>{t(`chat.mode.${chatMode}.title`)}</b>{" "}
<Trans
i18nKey={`chat.mode.${chatMode}.description`}
components={{ b: <b />, br: <br /> }}
/>
</p>
);
}

View File

@ -11,7 +11,11 @@ const { Workspace } = require("../models/workspace");
const { Document } = require("../models/documents"); const { Document } = require("../models/documents");
const { DocumentVectors } = require("../models/vectors"); const { DocumentVectors } = require("../models/vectors");
const { WorkspaceChats } = require("../models/workspaceChats"); const { WorkspaceChats } = require("../models/workspaceChats");
const { getVectorDbClass } = require("../utils/helpers"); const {
getVectorDbClass,
getLLMProvider,
getBaseLLMProviderModel,
} = require("../utils/helpers");
const { handleFileUpload, handlePfpUpload } = require("../utils/files/multer"); const { handleFileUpload, handlePfpUpload } = require("../utils/files/multer");
const { validatedRequest } = require("../utils/middleware/validatedRequest"); const { validatedRequest } = require("../utils/middleware/validatedRequest");
const { Telemetry } = require("../models/telemetry"); const { Telemetry } = require("../models/telemetry");
@ -38,6 +42,7 @@ const { purgeDocument } = require("../utils/files/purgeDocument");
const { getModelTag } = require("./utils"); const { getModelTag } = require("./utils");
const { searchWorkspaceAndThreads } = require("../utils/helpers/search"); const { searchWorkspaceAndThreads } = require("../utils/helpers/search");
const { workspaceParsedFilesEndpoints } = require("./workspacesParsedFiles"); const { workspaceParsedFilesEndpoints } = require("./workspacesParsedFiles");
const AIbitat = require("../utils/agents/aibitat");
function workspaceEndpoints(app) { function workspaceEndpoints(app) {
if (!app) return; if (!app) return;
@ -1059,6 +1064,23 @@ function workspaceEndpoints(app) {
} }
); );
app.get(
"/workspace/:slug/is-agent-command-available",
[validatedRequest, flexUserRoleValid([ROLES.all]), validWorkspaceSlug],
async (_, response) => {
try {
response.status(200).json({
showAgentCommand: await Workspace.isAgentCommandAvailable(
response.locals.workspace
),
});
} catch (error) {
console.error("Error checking if agent command is available:", error);
response.status(500).json({ showAgentCommand: false });
}
}
);
// Parsed Files in separate endpoint just to keep the workspace endpoints clean // Parsed Files in separate endpoint just to keep the workspace endpoints clean
workspaceParsedFilesEndpoints(app); workspaceParsedFilesEndpoints(app);
} }

View File

@ -33,6 +33,7 @@ function isNullOrNaN(value) {
*/ */
const Workspace = { const Workspace = {
VALID_CHAT_MODES: ["chat", "query", "automatic"],
defaultPrompt: SystemSettings.saneDefaultSystemPrompt, defaultPrompt: SystemSettings.saneDefaultSystemPrompt,
// Used for generic updates so we can validate keys in request body // Used for generic updates so we can validate keys in request body
@ -93,7 +94,8 @@ const Workspace = {
return n; return n;
}, },
chatMode: (value) => { chatMode: (value) => {
if (!value || !["chat", "query"].includes(value)) return "chat"; if (!value || !Workspace.VALID_CHAT_MODES.includes(value))
return "automatic";
return value; return value;
}, },
chatProvider: (value) => { chatProvider: (value) => {
@ -205,6 +207,7 @@ const Workspace = {
const workspace = await prisma.workspaces.create({ const workspace = await prisma.workspaces.create({
data: { data: {
name: this.validations.name(name), name: this.validations.name(name),
chatMode: "automatic",
...this.validateFields(additionalFields), ...this.validateFields(additionalFields),
slug, slug,
}, },
@ -609,6 +612,46 @@ const Workspace = {
return false; return false;
} }
}, },
/**
* Checks if the workspace's chat provider/model waterfall supports native tool calling.
* @param {Workspace} workspace - The workspace object to check
* @returns {Promise<boolean>}
*/
supportsNativeToolCalling: async function (workspace = {}) {
if (!workspace) return false;
const { getBaseLLMProviderModel } = require("../utils/helpers");
const AIbitat = require("../utils/agents/aibitat");
const provider =
workspace?.agentProvider ??
workspace?.chatProvider ??
process.env.LLM_PROVIDER;
const model =
workspace?.agentModel ??
workspace?.chatModel ??
getBaseLLMProviderModel({ provider });
const agentConfig = { provider, model };
const agentProvider = new AIbitat(agentConfig).getProviderForConfig(
agentConfig
);
const nativeToolCalling = await agentProvider.supportsNativeToolCalling?.();
return nativeToolCalling;
},
/**
* Checks if the agent command is available for a workspace
* by checking if the workspace's agent provider supports native tool calling.
* - If the workspaces chat provider/model supports native tool calling, then the agent command is NOT available
* as it will be assumed the model is capable of handling tool calls.
* Otherwise, the agent command is available and the user must opt-in to "@agent" to use tool calls.
* @param {Workspace} workspace - The workspace object to check
* @returns {Promise<boolean>}
*/
isAgentCommandAvailable: async function (workspace) {
if (workspace.chatMode !== "automatic") return true;
const nativeToolCalling = await this.supportsNativeToolCalling(workspace);
return nativeToolCalling === false;
},
}; };
module.exports = { Workspace }; module.exports = { Workspace };

View File

@ -82,6 +82,14 @@ class Provider {
return this._client; return this._client;
} }
/**
* Whether this provider supports native OpenAI-compatible tool calling.
* @returns {boolean|Promise<boolean>}
*/
supportsNativeToolCalling() {
return false;
}
/** /**
* *
* @param {string} provider - the string key of the provider LLM being loaded. * @param {string} provider - the string key of the provider LLM being loaded.

View File

@ -26,6 +26,15 @@ class AnthropicProvider extends Provider {
this.model = model; this.model = model;
} }
/**
* Whether this provider supports native OpenAI-compatible tool calling.
* - Anthropic always supports tool calling.
* @returns {boolean}
*/
supportsNativeToolCalling() {
return true;
}
/** /**
* Parses the cache control ENV variable * Parses the cache control ENV variable
* *

View File

@ -25,6 +25,15 @@ class AzureOpenAiProvider extends Provider {
return true; return true;
} }
/**
* Whether this provider supports native OpenAI-compatible tool calling.
* - Azure OpenAI always supports tool calling.
* @returns {boolean}
*/
supportsNativeToolCalling() {
return true;
}
/** /**
* Stream a chat completion from Azure OpenAI with tool calling. * Stream a chat completion from Azure OpenAI with tool calling.
* *

View File

@ -58,7 +58,8 @@ class AWSBedrockProvider extends InheritMultiple([Provider, UnTooled]) {
supportsNativeToolCalling() { supportsNativeToolCalling() {
if (this._supportsToolCalling !== null) return this._supportsToolCalling; if (this._supportsToolCalling !== null) return this._supportsToolCalling;
const supportsToolCalling = const supportsToolCalling =
process.env.PROVIDER_SUPPORTS_NATIVE_TOOL_CALLING?.includes("bedrock"); process.env.PROVIDER_SUPPORTS_NATIVE_TOOL_CALLING?.includes("bedrock") ||
false;
if (supportsToolCalling) if (supportsToolCalling)
this.providerLog("AWS Bedrock native tool calling is ENABLED via ENV."); this.providerLog("AWS Bedrock native tool calling is ENABLED via ENV.");

View File

@ -35,16 +35,13 @@ class GeminiProvider extends Provider {
return true; return true;
} }
get supportsAgentStreaming() { /**
// Tool call streaming results in a 400/503 error for all non-gemini models * Whether this provider supports native OpenAI-compatible tool calling.
// using the compatible v1beta/openai/ endpoint * - Gemini only supports tool calling for Gemini models.
if (!this.model.startsWith("gemini")) { * @returns {boolean}
this.providerLog( */
`Gemini: ${this.model} does not support tool call streaming.` supportsNativeToolCalling() {
); return this.supportsToolCalling;
return false;
}
return true;
} }
/** /**

View File

@ -61,7 +61,7 @@ class GenericOpenAiProvider extends InheritMultiple([Provider, UnTooled]) {
const supportsToolCalling = const supportsToolCalling =
process.env.PROVIDER_SUPPORTS_NATIVE_TOOL_CALLING?.includes( process.env.PROVIDER_SUPPORTS_NATIVE_TOOL_CALLING?.includes(
"generic-openai" "generic-openai"
); ) || false;
if (supportsToolCalling) if (supportsToolCalling)
this.providerLog( this.providerLog(

View File

@ -45,7 +45,8 @@ class GroqProvider extends InheritMultiple([Provider, UnTooled]) {
supportsNativeToolCalling() { supportsNativeToolCalling() {
if (this._supportsToolCalling !== null) return this._supportsToolCalling; if (this._supportsToolCalling !== null) return this._supportsToolCalling;
const supportsToolCalling = const supportsToolCalling =
process.env.PROVIDER_SUPPORTS_NATIVE_TOOL_CALLING?.includes("groq"); process.env.PROVIDER_SUPPORTS_NATIVE_TOOL_CALLING?.includes("groq") ||
false;
if (supportsToolCalling) if (supportsToolCalling)
this.providerLog("Groq supports native tool calling is ENABLED via ENV."); this.providerLog("Groq supports native tool calling is ENABLED via ENV.");

View File

@ -66,7 +66,8 @@ class LemonadeProvider extends InheritMultiple([Provider, UnTooled]) {
// Labels can be missing for tool calling models, so we also check if ENV flag is set // Labels can be missing for tool calling models, so we also check if ENV flag is set
const supportsToolCallingFlag = const supportsToolCallingFlag =
process.env.PROVIDER_SUPPORTS_NATIVE_TOOL_CALLING?.includes("lemonade"); process.env.PROVIDER_SUPPORTS_NATIVE_TOOL_CALLING?.includes("lemonade") ||
false;
if (supportsToolCallingFlag) { if (supportsToolCallingFlag) {
this.providerLog( this.providerLog(
"Lemonade supports native tool calling is ENABLED via ENV." "Lemonade supports native tool calling is ENABLED via ENV."

View File

@ -45,7 +45,8 @@ class LiteLLMProvider extends InheritMultiple([Provider, UnTooled]) {
supportsNativeToolCalling() { supportsNativeToolCalling() {
if (this._supportsToolCalling !== null) return this._supportsToolCalling; if (this._supportsToolCalling !== null) return this._supportsToolCalling;
const supportsToolCalling = const supportsToolCalling =
process.env.PROVIDER_SUPPORTS_NATIVE_TOOL_CALLING?.includes("litellm"); process.env.PROVIDER_SUPPORTS_NATIVE_TOOL_CALLING?.includes("litellm") ||
false;
if (supportsToolCalling) if (supportsToolCalling)
this.providerLog( this.providerLog(

View File

@ -45,7 +45,8 @@ class LocalAiProvider extends InheritMultiple([Provider, UnTooled]) {
supportsNativeToolCalling() { supportsNativeToolCalling() {
if (this._supportsToolCalling !== null) return this._supportsToolCalling; if (this._supportsToolCalling !== null) return this._supportsToolCalling;
const supportsToolCalling = const supportsToolCalling =
process.env.PROVIDER_SUPPORTS_NATIVE_TOOL_CALLING?.includes("localai"); process.env.PROVIDER_SUPPORTS_NATIVE_TOOL_CALLING?.includes("localai") ||
false;
if (supportsToolCalling) if (supportsToolCalling)
this.providerLog( this.providerLog(

View File

@ -30,6 +30,15 @@ class OpenAIProvider extends Provider {
return true; return true;
} }
/**
* Whether this provider supports native OpenAI-compatible tool calling.
* - OpenAI always supports tool calling.
* @returns {Promise<boolean>}
*/
supportsNativeToolCalling() {
return true;
}
/** /**
* Format the messages to the OpenAI API Responses format. * Format the messages to the OpenAI API Responses format.
* - If the message is our internal `function` type, then we need to map it to a function call + output format * - If the message is our internal `function` type, then we need to map it to a function call + output format

View File

@ -51,7 +51,9 @@ class OpenRouterProvider extends InheritMultiple([Provider, UnTooled]) {
supportsNativeToolCalling() { supportsNativeToolCalling() {
if (this._supportsToolCalling !== null) return this._supportsToolCalling; if (this._supportsToolCalling !== null) return this._supportsToolCalling;
const supportsToolCalling = const supportsToolCalling =
process.env.PROVIDER_SUPPORTS_NATIVE_TOOL_CALLING?.includes("openrouter"); process.env.PROVIDER_SUPPORTS_NATIVE_TOOL_CALLING?.includes(
"openrouter"
) || false;
if (supportsToolCalling) if (supportsToolCalling)
this.providerLog( this.providerLog(

View File

@ -3,6 +3,7 @@ const {
WorkspaceAgentInvocation, WorkspaceAgentInvocation,
} = require("../../models/workspaceAgentInvocation"); } = require("../../models/workspaceAgentInvocation");
const { writeResponseChunk } = require("../helpers/chat/responses"); const { writeResponseChunk } = require("../helpers/chat/responses");
const { Workspace } = require("../../models/workspace");
async function grepAgents({ async function grepAgents({
uuid, uuid,
@ -12,8 +13,15 @@ async function grepAgents({
user = null, user = null,
thread = null, thread = null,
}) { }) {
let nativeToolingEnabled = false;
// If the workspace is in automatic mode, check if the workspace supports native tooling
// to determine if the agent flow should be used or not.
if (workspace?.chatMode === "automatic")
nativeToolingEnabled = await Workspace.supportsNativeToolCalling(workspace);
const agentHandles = WorkspaceAgentInvocation.parseAgents(message); const agentHandles = WorkspaceAgentInvocation.parseAgents(message);
if (agentHandles.length > 0) { if (agentHandles.length > 0 || nativeToolingEnabled) {
const { invocation: newInvocation } = await WorkspaceAgentInvocation.new({ const { invocation: newInvocation } = await WorkspaceAgentInvocation.new({
prompt: message, prompt: message,
workspace: workspace, workspace: workspace,

View File

@ -13,13 +13,13 @@ const {
sourceIdentifier, sourceIdentifier,
} = require("./index"); } = require("./index");
const VALID_CHAT_MODE = ["chat", "query"]; const VALID_CHAT_MODE = ["automatic", "chat", "query"];
async function streamChatWithWorkspace( async function streamChatWithWorkspace(
response, response,
workspace, workspace,
message, message,
chatMode = "chat", chatMode = "automatic",
user = null, user = null,
thread = null, thread = null,
attachments = [] attachments = []