Merge pull request 'bugfix/ai-agent' (#42) from bugfix/ai-agent into release/v9.2.0

Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/desktop-sdk/pulls/42
This commit is contained in:
Oleg Korshul
2025-11-14 14:25:44 +00:00
16 changed files with 226 additions and 127 deletions

View File

@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.5 5C15.0389 5 17.9999 7.86724 18 11.4229C18 13.0282 17.3923 14.5291 16.3984 15.6914L19.8535 19.1465C20.0488 19.3417 20.0488 19.6583 19.8535 19.8535C19.6583 20.0488 19.3417 20.0488 19.1465 19.8535L15.6943 16.4014C14.5572 17.3902 13.0906 18 11.5 18C7.95263 18 5 15.0474 5 11.5C5 7.95262 7.95263 5 11.5 5ZM9.51172 12C9.56753 13.4751 9.86466 14.7614 10.2871 15.6768C10.7959 16.7791 11.2967 17 11.5 17C11.7033 17 12.2041 16.7791 12.7129 15.6768C13.1353 14.7614 13.4325 13.4751 13.4883 12H9.51172ZM6.02441 12C6.22613 14.1498 7.71186 15.9738 9.68945 16.6826C9.02439 15.5901 8.57685 13.9105 8.50977 12H6.02441ZM14.4902 12C14.4234 13.9047 13.9771 15.5791 13.3154 16.6719C15.2643 15.9524 16.7386 14.1256 16.9678 12H14.4902ZM9.68945 6.31641C7.71171 7.02513 6.22614 8.85008 6.02441 11H8.50977C8.57686 9.08904 9.02415 7.40892 9.68945 6.31641ZM11.5 6C11.2967 6 10.7959 6.22088 10.2871 7.32324C9.86466 8.23861 9.56753 9.52491 9.51172 11H13.4883C13.4325 9.52491 13.1353 8.23861 12.7129 7.32324C12.2041 6.22088 11.7033 6 11.5 6ZM13.3027 6.30469C13.9721 7.39688 14.4229 9.08203 14.4902 11H16.9814C16.808 8.82371 15.3109 7.00161 13.3027 6.30469Z" fill="#444444"/>
<path d="M12 4a8 8 0 0 1 7.545 5.334A8 8 0 0 1 20 12a8 8 0 0 1-.455 2.667 8.003 8.003 0 0 1-15.09 0A8 8 0 0 1 4 12c0-.934.16-1.832.455-2.666A8 8 0 0 1 12 4M9.3 15c.167.79.399 1.497.676 2.092C10.592 18.409 11.342 19 12 19s1.409-.59 2.024-1.908A9.8 9.8 0 0 0 14.7 15zm-3.625 0a7.02 7.02 0 0 0 4.038 3.616 6.6 6.6 0 0 1-.643-1.1c-.338-.723-.607-1.577-.791-2.516zm10.046 0c-.184.94-.453 1.793-.79 2.515a6.6 6.6 0 0 1-.645 1.101A7.02 7.02 0 0 0 18.326 15zm-10.43-5a7 7 0 0 0-.001 4h2.829c-.08-.64-.122-1.311-.122-2s.042-1.36.122-2zm3.837 0a15 15 0 0 0-.131 2c0 .696.046 1.367.13 2h5.745c.084-.633.13-1.304.13-2 0-.697-.046-1.368-.13-2zm6.753 0a16.4 16.4 0 0 1 0 4h2.829a7 7 0 0 0 0-4zM9.714 5.383A7.02 7.02 0 0 0 5.674 9H8.28c.184-.94.454-1.792.791-2.515.186-.399.402-.772.644-1.102M12 5c-.658 0-1.408.59-2.024 1.908A9.8 9.8 0 0 0 9.301 9h5.398a9.8 9.8 0 0 0-.675-2.092C13.41 5.59 12.658 5 12 5m2.285.382c.242.33.459.704.645 1.103.338.723.607 1.575.791 2.515h2.605a7.02 7.02 0 0 0-4.041-3.618" fill="#444444"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v16a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2z" fill="#969696"/>
<path d="M8 11a1 1 0 1 1 0 2 1 1 0 0 1 0-2m4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2m4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 330 B

View File

@ -37,14 +37,17 @@ const DropdownMenuComponent = ({
className={cn(
"dropdown-menu z-50 border border-[var(--drop-down-menu-border-color)] rounded-[8px] shadow-[var(--drop-down-menu-shadow)] bg-[var(--drop-down-menu-background-color)] py-[8px] max-h-56 overflow-y-auto flex flex-col gap-[4px]",
matchTriggerWidth
? "w-[var(--radix-dropdown-menu-trigger-width)]"
? "min-w-[150px] w-[var(--radix-dropdown-menu-trigger-width)]"
: "w-fit",
contentClassName
)}
style={maxWidth ? { maxWidth } : undefined}
>
{items.map((item, index) => (
<DropDownItem key={item.id || item.text || `item-${index}`} {...item} />
<DropDownItem
key={item.id || item.text || `item-${index}`}
{...item}
/>
))}
</DropdownMenu.Content>
</DropdownMenu.Portal>

View File

@ -16,6 +16,7 @@ import DocumentsIconUrl from "@/assets/formats/24/documents.svg?url";
import PdfIconUrl from "@/assets/formats/24/pdf.svg?url";
import SpreadsheetsIconUrl from "@/assets/formats/24/spreadsheets.svg?url";
import PresentationsIconUrl from "@/assets/formats/24/presentations.svg?url";
import UnknownFormatIconUrl from "@/assets/formats/24/unknown-format.svg?url";
import { IconButton } from "../icon-button";
@ -50,7 +51,7 @@ const FileItem = ({ file, withoutClose }: FileItemProps) => {
? SpreadsheetsIconUrl
: isPresentationFile
? PresentationsIconUrl
: null;
: UnknownFormatIconUrl;
return (
<div

View File

@ -35,12 +35,12 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
React.useLayoutEffect(() => {
if (window.RendererProcessVariable) {
i18n.changeLanguage("en");
i18n.changeLanguage(window.RendererProcessVariable.lang);
}
window.on_update_plugin_info = (info) => {
if (info.lang) {
i18n.changeLanguage("en");
i18n.changeLanguage(info.lang);
}
if (info.theme) {

View File

@ -2,6 +2,15 @@ import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import en from "./translations/en.json";
import ru from "./translations/ru.json";
import cs from "./translations/cs.json";
import de from "./translations/de.json";
import es from "./translations/es.json";
import fr from "./translations/fr.json";
import it from "./translations/it.json";
import pl from "./translations/pl.json";
import ptBr from "./translations/pt-br.json";
import sk from "./translations/sk.json";
i18n
.use(initReactI18next) // passes i18n down to react-i18next
@ -10,6 +19,33 @@ i18n
en: {
translation: en,
},
ru: {
translation: ru,
},
"cs-CZ": {
translation: cs,
},
de: {
translation: de,
},
es: {
translation: es,
},
fr: {
translation: fr,
},
it: {
translation: it,
},
pl: {
translation: pl,
},
"pt-BR": {
translation: ptBr,
},
"sl-SI": {
translation: sk,
},
},
fallbackLng: "en",

View File

@ -7,6 +7,7 @@ import DocumentsIconSvg from "@/assets/formats/24/documents.svg?url";
import SpreadsheetsIconSvg from "@/assets/formats/24/spreadsheets.svg?url";
import PdfIconSvg from "@/assets/formats/24/pdf.svg?url";
import PresentationsIconSvg from "@/assets/formats/24/presentations.svg?url";
import UnknownFormatIconSvg from "@/assets/formats/24/unknown-format.svg?url";
import useAttachmentsStore from "@/store/useAttachmentsStore";
@ -99,7 +100,7 @@ const ComposerActionAttachment = () => {
} else if (isPresentation(file.type)) {
icon = PresentationsIconSvg;
} else {
icon = null;
icon = UnknownFormatIconSvg;
}
return {

View File

@ -77,6 +77,23 @@ const SelectModel = () => {
(p) => p.name === currentProvider?.name
);
React.useEffect(() => {
if ((!currentModel || !currentProvider) && providers.length > 0) {
const providerInfo = providers[0];
const model = providersModels.get(providerInfo.name)?.[0];
if (!model) return;
onSelectModel(providerInfo, model.id);
}
}, [
currentModel,
currentProvider,
providers,
providersModels,
onSelectModel,
]);
return (
<ComboBox
placeholder={t("SelectModel")}

View File

@ -16,6 +16,7 @@ import MoreIconSvgUrl from "@/assets/more.svg?url";
import RemoveIconSvgUrl from "@/assets/btn-remove.svg?url";
import ResetIconSvgUrl from "@/assets/btn-reset.svg?url";
import NavigationIconSvgUrl from "@/assets/btn-menu-navigation.svg?url";
import StatusErrorIconUrl from "@/assets/status.error.svg?url";
import type { TMCPItem } from "@/lib/types";
@ -111,6 +112,14 @@ const AvailableToolsItem = ({
<p className="text-[var(--servers-available-tools-item-name-color)]">
{name}
</p>
{!isLoadingAction && isStoped ? (
<IconButton
iconName={StatusErrorIconUrl}
size={16}
disableHover
noColor
/>
) : null}
{isLoading ? null : (
<p className="font-normal text-[14px] text-[var(--servers-available-tools-sub-header-color)]">
<span className="text-[var(--servers-available-tools-current-tool-color)]">

View File

@ -119,7 +119,7 @@ class AnthropicProvider
system: this.systemPrompt,
tools: this.tools,
stream: true,
max_tokens: 2048,
max_tokens: 30000,
tool_choice: {
disable_parallel_tool_use: true,
type: "auto",
@ -315,11 +315,18 @@ class AnthropicProvider
const body = modelsRes.data;
return body.map((model) => ({
id: model.id,
name: model.display_name,
provider: "anthropic" as const,
}));
return body
.filter(
(model) =>
model.id.includes("claude-haiku-4-5") ||
model.id.includes("claude-sonnet-4-5") ||
model.id.includes("claude-opus-4-1")
)
.map((model) => ({
id: model.id,
name: model.display_name,
provider: "anthropic" as const,
}));
} catch (error) {
console.log(error);
return [];

View File

@ -126,8 +126,6 @@ class OpenAIProvider
model: this.modelKey,
tools: this.tools,
stream: true,
max_completion_tokens: 2048,
});
this.prevMessages.push(...convertedMessage);
@ -317,11 +315,21 @@ class OpenAIProvider
const response: OpenAIModel[] = (await newClient.models.list()).data;
return response.map((model) => ({
id: model.id,
name: model.id,
provider: "openai" as const,
}));
return response
.filter(
(model) =>
model.id === "gpt-4.1" ||
model.id === "gpt-5" ||
model.id === "gpt-5.1-2025-11-13"
)
.map((model) => ({
id: model.id,
name:
model.id === "gpt-5.1-2025-11-13"
? "GPT-5.1"
: model.id.toUpperCase(),
provider: "openai" as const,
}));
};
}

View File

@ -124,8 +124,6 @@ class TogetherProvider
model: this.modelKey,
tools: this.tools,
stream: true,
max_tokens: 2048,
});
this.prevMessages.push(...convertedMessage);
@ -318,11 +316,17 @@ class TogetherProvider
(m) => m.type === "chat"
);
return response.map((model) => ({
id: model.id,
name: model.display_name ?? model.id,
provider: "openai" as const,
}));
return response
.filter(
(m) =>
m.id === "Qwen/Qwen3-235B-A22B-fp8-tput" ||
m.id === "deepseek-ai/DeepSeek-V3.1"
)
.map((model) => ({
id: model.id,
name: model.display_name ?? model.id,
provider: "openai" as const,
}));
};
}

View File

@ -180,6 +180,8 @@ class WebSearch {
},
},
]);
window.dispatchEvent(new CustomEvent("tools-changed"));
};
getWebSearchEnabled = () => {

View File

@ -37,7 +37,7 @@
"Yes": "Да",
"No": "Нет",
"WelcomeTitle": "Чем я могу помочь?",
"WelcomeDescription": "Бесплатный ИИ-чат, помощник в написании и генератор идей",
"WelcomeDescription": "Бесплатный ИИ-чат, помощник в создании документов и генератор идей",
"Rename": "Переименовать",
"Download": "Загрузить",
"Search": "Поиск...",