diff --git a/apps/internal-ui/src/features/integrations/AddIntegrationButton.tsx b/apps/internal-ui/src/features/integrations/AddIntegrationButton.tsx
index c864111..96b7e1e 100644
--- a/apps/internal-ui/src/features/integrations/AddIntegrationButton.tsx
+++ b/apps/internal-ui/src/features/integrations/AddIntegrationButton.tsx
@@ -1,4 +1,5 @@
import { Dropdown } from "antd";
+import { useState } from "react";
import { t } from "../../i18n";
import { Icon } from "../../shared/icons";
import { Button } from "../../shared/ui-controls";
@@ -6,16 +7,19 @@ import type { ServerKind } from "./external/types";
import "./add-integration.css";
export function AddIntegrationButton({ onEntry, onServer }: { onEntry: () => void; onServer: (kind: ServerKind) => void }) {
- const option = (icon: "message" | "server" | "swap", title: string, hint: string, action: () => void) =>
- ;
- return
+ ;
+ return { setOpen(false); if (key === "entry") onEntry(); else onServer(key as ServerKind); },
+ items: [
{ type: "group", label: t("servers.entry"), children: [
- { key: "entry", label: option("message", t("servers.entry_title"), t("servers.entry_hint"), onEntry) },
+ { key: "entry", label: option("message", t("servers.entry_title"), t("servers.entry_hint")) },
] },
{ type: "divider" },
{ type: "group", label: t("servers.external_group"), children: [
- { key: "mcp", label: option("server", t("servers.new_mcp"), t("servers.mcp_hint"), () => onServer("mcp")) },
- { key: "http", label: option("swap", t("servers.new_http"), t("servers.http_hint"), () => onServer("http")) },
+ { key: "mcp", label: option("server", t("servers.new_mcp"), t("servers.mcp_hint")) },
+ { key: "http", label: option("swap", t("servers.new_http"), t("servers.http_hint")) },
] },
- ] }}>;
+ ] }}>;
}
diff --git a/apps/internal-ui/src/features/integrations/ConnectionsTable.tsx b/apps/internal-ui/src/features/integrations/ConnectionsTable.tsx
index 7de7695..ba6bf7e 100644
--- a/apps/internal-ui/src/features/integrations/ConnectionsTable.tsx
+++ b/apps/internal-ui/src/features/integrations/ConnectionsTable.tsx
@@ -4,6 +4,7 @@ import { PROVIDERS, type Integration } from "./model";
import { ConnectionIcon, RowActions, StatusCell } from "./rows";
import { t, tn } from "../../i18n";
import { serverHost } from "./external/model";
+import "./connections-table.css";
// Подстрока подключения (SPEC-CHATBALLS-0025 §2.4): провайдер + идентификатор.
function subtitle(integration: Integration): string {
@@ -28,44 +29,47 @@ type ConnectionsTableProps = {
export function ConnectionsTable({ items, testingId, onTest, onEdit, onToggleActive, onDelete }: ConnectionsTableProps) {
return (
-
-
-
-
- | {t("settings.title")} |
- {t("servers.agent_tools")} |
- {t("common.status_2")} |
- |
-
-
-
- {items.map((item) => (
-
- |
-
-
- {item.provider === "WEB" || item.kind === "EXTERNAL_SERVER"
- ?
- : {item.name}}{subtitle(item)}
-
- |
-
- {item.externalServer ? {tn("servers.count", item.externalServer.type === "http" ? 1 : item.externalServer.tools?.length ?? 0)} : item.channel
- ? (
-
- {item.channel.name}
-
- )
- : —}
- |
- |
-
-
- |
+ <>
+
+
+
+
+ | {t("settings.title")} |
+ {t("servers.agent_tools")} |
+ {t("common.status_2")} |
+ |
- ))}
-
-
-
+
+
+ {items.map((item) => (
+
+ |
+
+
+ {item.provider === "WEB" || item.kind === "EXTERNAL_SERVER"
+ ?
+ : {item.name}}{subtitle(item)}
+
+ |
+
+ {item.externalServer ? {tn("servers.count", item.externalServer.type === "http" ? 1 : item.externalServer.tools?.length ?? 0)} : item.channel
+ ? (
+
+ {item.channel.name}
+
+ )
+ : —}
+ |
+ |
+
+
+ |
+
+ ))}
+
+
+
+ {t("servers.list_note")}
+ >
);
}
diff --git a/apps/internal-ui/src/features/integrations/IntegrationPageLayout.tsx b/apps/internal-ui/src/features/integrations/IntegrationPageLayout.tsx
new file mode 100644
index 0000000..6580486
--- /dev/null
+++ b/apps/internal-ui/src/features/integrations/IntegrationPageLayout.tsx
@@ -0,0 +1,23 @@
+import type { ReactNode } from "react";
+import { SectionMenu, type SectionMenuItem } from "../../shared/SectionMenu";
+import "../support-portals/styles-detail.css";
+import "../support-portals/styles-settings.css";
+import "./web-integration.css";
+
+export function IntegrationPageLayout({ header, items, activeKey, note, onSelect, children, className = "" }: {
+ header: ReactNode;
+ items: readonly SectionMenuItem[];
+ activeKey: Key;
+ note: string;
+ onSelect: (key: Key) => void;
+ children: ReactNode;
+ className?: string;
+}) {
+ return ;
+}
diff --git a/apps/internal-ui/src/features/integrations/IntegrationSettingsPage.tsx b/apps/internal-ui/src/features/integrations/IntegrationSettingsPage.tsx
index 67b5f13..216f120 100644
--- a/apps/internal-ui/src/features/integrations/IntegrationSettingsPage.tsx
+++ b/apps/internal-ui/src/features/integrations/IntegrationSettingsPage.tsx
@@ -1,12 +1,9 @@
-import { t } from "../../i18n";
-import { ContentState } from "../../shared/ui";
-import { Icon } from "../../shared/icons";
-import { Button } from "../../shared/ui-controls";
import { useIntegrations } from "../settings/useIntegrations";
import { WebIntegrationPage } from "./WebIntegrationPage";
import { ExternalServerPage } from "./external/ExternalServerPage";
import type { ServerKind } from "./external/types";
import { ServerPageLoading } from "./external/ServerPageLoading";
+import { ServerPageState } from "./external/ServerPageState";
export function IntegrationSettingsPage({ integrationId, createKind, onCreated, onOpenSettings, onBack }: {
integrationId?: number; createKind?: ServerKind; onCreated: (id: number) => void; onOpenSettings: () => void; onBack: () => void;
@@ -14,15 +11,9 @@ export function IntegrationSettingsPage({ integrationId, createKind, onCreated,
const list = useIntegrations(true);
const integration = list.items.find((i) => i.id === integrationId);
if (list.loading) return ;
- if (list.failed || (!createKind && !integration)) return }
- title={t(list.failed ? "servers.load_failed" : "servers.not_found")}
- text={t(list.failed ? "servers.load_failed_hint" : "servers.not_found_hint")}
- action={list.failed ?
- : } />;
+ if (list.failed || (!createKind && !integration)) return ;
if (integration?.provider === "WEB") return ;
if (createKind || integration?.externalServer) return ;
- return } title={t("servers.not_found")} text={t("servers.not_found_hint")}
- action={} />;
+ return ;
}
diff --git a/apps/internal-ui/src/features/integrations/WebIntegrationPage.tsx b/apps/internal-ui/src/features/integrations/WebIntegrationPage.tsx
index 3eb314e..b1af14b 100644
--- a/apps/internal-ui/src/features/integrations/WebIntegrationPage.tsx
+++ b/apps/internal-ui/src/features/integrations/WebIntegrationPage.tsx
@@ -1,9 +1,8 @@
import { useState } from "react";
-import "../support-portals/styles-detail.css";
-import "../support-portals/styles-settings.css";
import { fmt, t } from "../../i18n";
-import { SectionMenu, type SectionMenuItem } from "../../shared/SectionMenu";
+import type { SectionMenuItem } from "../../shared/SectionMenu";
+import { IntegrationPageLayout } from "./IntegrationPageLayout";
import { EmptyState, LoadingState } from "../../shared/ui";
import { DeleteIntegrationDialog } from "./DeleteIntegrationDialog";
import { WebIntegrationBasics } from "./WebIntegrationBasics";
@@ -39,36 +38,33 @@ export function WebIntegrationPage({ integrationId, onOpenSettings, onBack }: {
if (!integration) return ;
return (
-
-
-
-
{
- if (item.key === "fields") return { ...item, hint: { text: fmt.number(fieldCount ?? integration.config.fields?.length ?? 0) } };
- if (item.key === "form" && (formEnabled ?? integration.config.preChat?.enabled)) return { ...item, hint: { text: t("pre_chat.on") } };
- return item;
- })}
- activeKey={section}
- note={t("settings.web_changes_apply_after_save")}
- onSelect={(next) => { if (next === "danger") setConfirmingDelete(true); else setSection(next); }}
- />
-
-
-
-
{t("portals.basics")}
-
-
+ <>
+
}
+ items={sections.map((item) => {
+ if (item.key === "fields") return { ...item, hint: { text: fmt.number(fieldCount ?? integration.config.fields?.length ?? 0) } };
+ if (item.key === "form" && (formEnabled ?? integration.config.preChat?.enabled)) return { ...item, hint: { text: t("pre_chat.on") } };
+ return item;
+ })}
+ activeKey={section}
+ note={t("settings.web_changes_apply_after_save")}
+ onSelect={(next) => { if (next === "danger") setConfirmingDelete(true); else setSection(next); }}
+ >
+
+
+
{t("portals.basics")}
-
-
-
-
- {section === "look" &&
}
+
-
+
+
+
+
+ {section === "look" &&
}
+
{confirmingDelete &&
setConfirmingDelete(false)} onDeleted={onBack} />}
-
+ >
);
}
diff --git a/apps/internal-ui/src/features/integrations/add-integration.css b/apps/internal-ui/src/features/integrations/add-integration.css
index 5566c28..95de68a 100644
--- a/apps/internal-ui/src/features/integrations/add-integration.css
+++ b/apps/internal-ui/src/features/integrations/add-integration.css
@@ -2,4 +2,8 @@
.app-dropdown.is-server-add .ant-dropdown-menu-item-group-title { padding: 8px 10px 4px; font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--n-4); }
.app-dropdown.is-server-add .ant-dropdown-menu-item button > i { display: grid; place-items: center; flex: none; width: 28px; height: 28px; border-radius: 8px; background: var(--n-9); color: var(--n-3); }
.app-dropdown.is-server-add .ant-dropdown-menu-item strong { font-size: 13px; font-weight: 600; color: var(--n-1); }
-.app-dropdown.is-server-add .ant-dropdown-menu-item button small { font-size: 11.5px; font-weight: 400; line-height: 1.4; }
+.app-dropdown.is-server-add .ant-dropdown-menu-item button { align-items: flex-start; gap: 10px; white-space: normal; }
+.app-dropdown.is-server-add .ant-dropdown-menu-item button > span { flex: 1; min-width: 0; }
+.app-dropdown.is-server-add .ant-dropdown-menu-item button small { color: var(--n-4); font-size: 11.5px; font-weight: 400; line-height: 1.4; }
+.integration-add-button.primary-button.row-menu-button { width: auto; min-height: 34px; height: 34px; padding: 0 12px 0 14px; gap: 7px; border-radius: 8px; font-size: 13px; color: var(--on-primary); background: var(--primary); }
+.integration-add-button.primary-button.row-menu-button:hover, .integration-add-button.primary-button.row-menu-button[aria-expanded="true"] { color: var(--on-primary); background: var(--primary-hover); }
diff --git a/apps/internal-ui/src/features/integrations/connections-table.css b/apps/internal-ui/src/features/integrations/connections-table.css
new file mode 100644
index 0000000..ba0f04a
--- /dev/null
+++ b/apps/internal-ui/src/features/integrations/connections-table.css
@@ -0,0 +1,15 @@
+.integrations-list-note { margin: 12px 4px 0; color: var(--n-4); font-size: 12.5px; line-height: 1.5; }
+.integration-tools-count { font-size: 13px; font-weight: 500; }
+.integrations-connections-table, .integrations-connections-table thead, .integrations-connections-table tbody { display: block; }
+.integrations-connections-table tr { display: grid; grid-template-columns: minmax(0,1.8fr) minmax(0,1.1fr) minmax(0,1.3fr) 150px; gap: 16px; align-items: center; padding: 10px 20px; border-bottom: 1px solid var(--n-9); }
+.integrations-connections-table tbody tr { min-height: 62px; }
+.integrations-connections-table thead tr { background: var(--surface-sidebar); border-bottom-color: var(--n-8); }
+.integrations-connections-table tbody tr:last-child { border-bottom: 0; }
+.settings-content .integrations-connections-table tr > :is(th,td), .settings-content .integrations-connections-table tr > :is(th,td):first-child, .settings-content .integrations-connections-table tr > :is(th,td):last-child { min-width: 0; height: auto; padding: 0; border: 0; background: transparent; }
+.integrations-connections-table .product-cell > span:last-child { min-width: 0; flex: 1; }
+.integrations-connections-table .product-cell .link.is-strong { max-width: 100%; }
+.settings-content .integrations-connections-table .product-cell strong, .settings-content .integrations-connections-table .product-cell .link.is-strong { display: block; font-size: 14px; font-weight: 700; }
+.integrations-connections-table .product-cell strong, .integrations-connections-table .product-cell .link, .integrations-connections-table .product-cell small, .integrations-connections-table .integration-status > small { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
+.settings-content .integrations-connections-table .integration-status { gap: 4px; }
+.settings-content .integrations-connections-table .integration-status > small { font-size: 12px; }
+.integrations-connections-table .integration-agent { max-width: 100%; overflow: hidden; white-space: nowrap; }
diff --git a/apps/internal-ui/src/features/integrations/external/ExternalServerPage.tsx b/apps/internal-ui/src/features/integrations/external/ExternalServerPage.tsx
index f3b4255..980f5ac 100644
--- a/apps/internal-ui/src/features/integrations/external/ExternalServerPage.tsx
+++ b/apps/internal-ui/src/features/integrations/external/ExternalServerPage.tsx
@@ -1,6 +1,7 @@
import { useState } from "react";
import { fmt, t } from "../../../i18n";
-import { SectionMenu, type SectionMenuItem } from "../../../shared/SectionMenu";
+import type { SectionMenuItem } from "../../../shared/SectionMenu";
+import { IntegrationPageLayout } from "../IntegrationPageLayout";
import type { Integration } from "../model";
import { DeleteIntegrationDialog } from "../DeleteIntegrationDialog";
import { HttpParameters } from "./HttpParameters";
@@ -10,9 +11,6 @@ import { ServerConnection } from "./ServerConnection";
import { ServerHeader } from "./ServerHeader";
import { useServerEditor } from "./useServerEditor";
import type { ServerKind } from "./types";
-import "../../support-portals/styles-detail.css";
-import "../../support-portals/styles-settings.css";
-import "../web-integration.css";
import "./styles.css";
import "./tools.css";
import "./parameters.css";
@@ -28,22 +26,20 @@ export function ExternalServerPage({ initial, kind, integrations, onCreated, onB
const [deleting, setDeleting] = useState(false);
const mcp = kind === "mcp";
const items: SectionMenuItem[] = [
- { key: "main", label: t(mcp ? "servers.connection" : "servers.tool"), icon: mcp ? "plug" : "wrench" },
- mcp ? { key: "tools", label: t("ai.tools"), icon: "wrench", hint: { text: fmt.number(editor.integration?.externalServer?.tools?.length ?? 0) } }
- : { key: "parameters", label: t("servers.parameters"), icon: "list", hint: { text: fmt.number(editor.draft.externalServer.parameters?.length ?? 0) } },
- { key: "delete", label: t("servers.delete"), icon: "trash", danger: true, disabled: !editor.integration, divider: true },
+ { key: "main", label: t(mcp ? "servers.connection" : "servers.tool"), icon: "settings" },
+ mcp ? { key: "tools", label: t("ai.tools"), icon: "wrench", hint: { text: fmt.number(editor.integration?.externalServer?.tools?.length ?? 0) }, divider: true }
+ : { key: "parameters", label: t("servers.parameters"), icon: "list", hint: { text: fmt.number(editor.draft.externalServer.parameters?.length ?? 0) }, divider: true },
+ { key: "delete", label: t(mcp ? "servers.delete" : "servers.delete_tool"), icon: "trash", danger: true, disabled: !editor.integration },
];
- return
-
-
-
key === "delete" ? setDeleting(true) : setSection(key)} />
-
+ return <>
+ }
+ items={items} activeKey={section} note={t("servers.changes_note")}
+ onSelect={(key) => key === "delete" ? setDeleting(true) : setSection(key)}>
{section === "main" && (mcp ? : )}
{section === "tools" && setSection("main")} />}
{section === "parameters" && }
-
-
+
{deleting && editor.integration && setDeleting(false)} onDeleted={onBack} />}
- ;
+ >;
}
diff --git a/apps/internal-ui/src/features/integrations/external/ServerHeader.tsx b/apps/internal-ui/src/features/integrations/external/ServerHeader.tsx
index 3436e3d..f6dd6ed 100644
--- a/apps/internal-ui/src/features/integrations/external/ServerHeader.tsx
+++ b/apps/internal-ui/src/features/integrations/external/ServerHeader.tsx
@@ -1,14 +1,17 @@
import { t, tn } from "../../../i18n";
import { Icon } from "../../../shared/icons";
-import { CopyButton } from "../../../shared/ui-controls";
-import { StatusPill } from "../../../shared/ui";
+import { CopyButton, ToneBadge } from "../../../shared/ui-controls";
+import { STATUS_META } from "../model";
import type { ServerEditor } from "./useServerEditor";
export function ServerHeader({ editor, onOpenSettings, onBack }: { editor: ServerEditor; onOpenSettings: () => void; onBack: () => void }) {
const server = editor.integration?.externalServer ?? editor.draft.externalServer;
const mcp = server.type === "mcp";
const name = editor.integration?.name || t(mcp ? "servers.new_mcp" : "servers.new_http");
- const status = !editor.integration ? "draft" : !editor.integration.isActive ? "disabled" : editor.integration.status === "OK" ? "healthy" : editor.integration.status === "ERROR" ? "error" : "unchecked";
+ const status = editor.integration
+ ? editor.integration.isActive ? STATUS_META[editor.integration.status]
+ : { bg: "var(--n-9)", color: "var(--n-4)", label: t("settings.disabled") }
+ : { bg: "var(--n-9)", color: "var(--n-4)", label: t("common.draft") };
return
{name}
- {t(mcp ? "servers.new_mcp" : "servers.new_http")} · {tn("servers.count", mcp ? server.tools?.length ?? 0 : 1)}
+ {status.label}{t(mcp ? "servers.new_mcp" : "servers.new_http")} · {tn("servers.count", mcp ? server.tools?.length ?? 0 : 1)}
{server.url && {mcp ? "" : `${server.method ?? "GET"} `}{server.url}{t(mcp ? "servers.address_note" : "servers.request_note")}
}
;
diff --git a/apps/internal-ui/src/features/integrations/external/ServerPageLoading.tsx b/apps/internal-ui/src/features/integrations/external/ServerPageLoading.tsx
index ab2e4a1..5b17542 100644
--- a/apps/internal-ui/src/features/integrations/external/ServerPageLoading.tsx
+++ b/apps/internal-ui/src/features/integrations/external/ServerPageLoading.tsx
@@ -1,10 +1,10 @@
import { t } from "../../../i18n";
-import { Icon } from "../../../shared/icons";
+import "./styles.css";
// X9: шапка-каркас и центральный индикатор загрузки.
export function ServerPageLoading() {
return
- {t("servers.loading")}
+
;
}
diff --git a/apps/internal-ui/src/features/integrations/external/ServerPageState.tsx b/apps/internal-ui/src/features/integrations/external/ServerPageState.tsx
new file mode 100644
index 0000000..0ffa713
--- /dev/null
+++ b/apps/internal-ui/src/features/integrations/external/ServerPageState.tsx
@@ -0,0 +1,21 @@
+import { t } from "../../../i18n";
+import { Icon } from "../../../shared/icons";
+import { ContentState } from "../../../shared/ui";
+import { Button } from "../../../shared/ui-controls";
+import "./styles.css";
+
+export function ServerPageState({ failed = false, onRetry, onBack }: {
+ failed?: boolean;
+ onRetry: () => void;
+ onBack: () => void;
+}) {
+ const errorIcon = ;
+ return }
+ title={t(failed ? "servers.load_failed" : "servers.not_found")}
+ text={t(failed ? "servers.load_failed_hint" : "servers.not_found_hint")}
+ action={failed ?
+ : } />;
+}
diff --git a/apps/internal-ui/src/features/integrations/external/ServerWarning.tsx b/apps/internal-ui/src/features/integrations/external/ServerWarning.tsx
index ccf78d7..83beb88 100644
--- a/apps/internal-ui/src/features/integrations/external/ServerWarning.tsx
+++ b/apps/internal-ui/src/features/integrations/external/ServerWarning.tsx
@@ -1,10 +1,11 @@
import { t } from "../../../i18n";
-import { ShieldIcon } from "../../../shared/icons";
import { helpArticleUrl } from "../../../shared/help";
export function ServerWarning() {
return ;
}
diff --git a/apps/internal-ui/src/features/integrations/external/styles.css b/apps/internal-ui/src/features/integrations/external/styles.css
index de500e9..6f9448a 100644
--- a/apps/internal-ui/src/features/integrations/external/styles.css
+++ b/apps/internal-ui/src/features/integrations/external/styles.css
@@ -57,10 +57,13 @@
.server-confirm-modal .ant-modal-footer { padding: 14px 24px; margin: 0; border-top: 1px solid var(--n-8); }
.server-confirm-check { display: flex; align-items: center; gap: 9px; font-size: 13px; color: var(--n-2); cursor: pointer; }
.server-confirm-check input { accent-color: var(--primary); }
-.server-page-state { display: flex; flex: 1; flex-direction: column; align-items: center; justify-content: center; width: 100%; margin: 0; border: 0; border-radius: 0; box-shadow: none; background: var(--surface-feed); }
-.server-page-state > p { max-width: 360px; }
-.server-page-state .content-state-icon { width: 40px; height: 40px; border-radius: 50%; background: var(--n-9); color: var(--n-4); }
-.server-page-state.is-error .content-state-icon { background: var(--error-bg); color: var(--error-text); }
+.content-state.server-page-state { display: flex; flex: 1; flex-direction: column; align-items: center; justify-content: center; width: 100%; height: 100%; padding: 30px; margin: 0; border: 0; border-radius: 0; box-shadow: none; background: var(--surface-feed); }
+.content-state.server-page-state > strong { margin-bottom: 6px; color: var(--n-2); }
+.content-state.server-page-state > p { max-width: 360px; margin-bottom: 14px; color: var(--n-4); }
+.content-state.server-page-state .content-state-icon { width: 40px; height: 40px; margin-bottom: 12px; border-radius: 50%; background: var(--n-9); color: var(--n-4); }
+.content-state.server-page-state.is-error .content-state-icon { background: var(--error-bg); color: var(--error-text); }
+.content-state.server-page-state .secondary-button { height: 34px; padding: 0 14px; border-radius: 8px; font-size: 13px; font-weight: 500; }
+.content-state.server-page-state .link.is-strong { font-size: 13px; font-weight: 600; }
.server-page-loading { display: flex; height: 100%; flex-direction: column; background: var(--surface-feed); }
.server-page-loading i { display: block; height: 14px; border-radius: 5px; background: var(--n-9); }
.server-page-loading header { padding: 18px 22px 16px; border-bottom: 1px solid var(--n-8); background: var(--surface-card); }
diff --git a/apps/internal-ui/src/features/settings/useIntegrations.ts b/apps/internal-ui/src/features/settings/useIntegrations.ts
index f110119..19ef3f7 100644
--- a/apps/internal-ui/src/features/settings/useIntegrations.ts
+++ b/apps/internal-ui/src/features/settings/useIntegrations.ts
@@ -21,6 +21,7 @@ export function useIntegrations(enabled: boolean): IntegrationsState {
const reload = useCallback(() => {
if (!enabled) return;
+ setLoading(true);
setFailed(false);
api<{ items: Integration[] }>("/api/v1/integrations/")
.then((payload) => setItems(payload.items))
diff --git a/apps/internal-ui/src/i18n/external-servers.en.ts b/apps/internal-ui/src/i18n/external-servers.en.ts
index c675bbb..6c0e903 100644
--- a/apps/internal-ui/src/i18n/external-servers.en.ts
+++ b/apps/internal-ui/src/i18n/external-servers.en.ts
@@ -11,6 +11,7 @@ export const externalServersEn: Record
"servers.mcp_hint": "A ready server with a set of tools: orders, catalog, prices",
"servers.http_hint": "One request to your API, such as order status by number",
"servers.agent_tools": "Agent · tools",
+ "servers.list_note": "The server name opens its page. Enable tools for each agent separately in the Tools section of the agent card.",
"servers.count": { one: "{count} tool", other: "{count} tools" },
"servers.new_mcp": "MCP server",
"servers.new_http": "HTTP request",
@@ -18,6 +19,8 @@ export const externalServersEn: Record
"servers.tool": "Tool",
"servers.parameters": "Parameters",
"servers.delete": "Delete server",
+ "servers.delete_tool": "Delete tool",
+ "servers.retry": "Retry",
"servers.changes_note": "Changes reach agents immediately after saving.",
"servers.connection_lead": "The server agents use to retrieve your organization's data: order statuses, menus and prices.",
"servers.enabled": "Server enabled",
diff --git a/apps/internal-ui/src/i18n/external-servers.ru.ts b/apps/internal-ui/src/i18n/external-servers.ru.ts
index 9b18dde..27a34a9 100644
--- a/apps/internal-ui/src/i18n/external-servers.ru.ts
+++ b/apps/internal-ui/src/i18n/external-servers.ru.ts
@@ -8,6 +8,7 @@ export const externalServersRu = {
"servers.mcp_hint": "Готовый сервер с набором инструментов: заказы, каталог, цены",
"servers.http_hint": "Один запрос к вашему API — например, статус заказа по номеру",
"servers.agent_tools": "Агент · инструменты",
+ "servers.list_note": "Название сервера открывает его страницу. Инструменты включаются для каждого агента отдельно — на карточке агента, блок «Инструменты».",
"servers.count": { one: "{count} инструмент", few: "{count} инструмента", many: "{count} инструментов", other: "{count} инструмента" },
"servers.new_mcp": "MCP-сервер",
"servers.new_http": "HTTP-запрос",
@@ -15,6 +16,8 @@ export const externalServersRu = {
"servers.tool": "Инструмент",
"servers.parameters": "Параметры",
"servers.delete": "Удалить сервер",
+ "servers.delete_tool": "Удалить инструмент",
+ "servers.retry": "Повторить",
"servers.changes_note": "Изменения доходят до агентов сразу после сохранения.",
"servers.connection_lead": "Сервер, через который агенты получают данные вашей организации: статусы заказов, меню, цены.",
"servers.enabled": "Сервер включён",