diff --git a/README.md b/README.md index ac81cf8f..f79b1647 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ every little fix. And it needs no enterprise license. **Same server as standalone docmost-mcp — just bundled.** This is the exact [docmost-mcp](https://github.com/vvzvlad/docmost-mcp) you can also run on its own; embedding it doesn't make it more capable, you simply don't have to install and run a separate -process. An admin flips one toggle in **Workspace settings → AI & MCP** and any MCP client +process. An admin flips one toggle in **Workspace settings → AI** and any MCP client points at `${APP_URL}/mcp`. ### AI agent chat @@ -88,9 +88,9 @@ community feature, with no enterprise license. Open it from the page header; the across pages. - **Web access via external MCP.** Admins can connect external MCP servers (e.g. Tavily) to give the agent web search / internet access. -- **Bring your own model.** Configure the provider (OpenAI, Gemini or Ollama), model and API - key in **Workspace settings → AI & MCP → AI / Models**. The key is encrypted and never - leaves the server. +- **Bring your own model.** Configure an OpenAI-compatible endpoint — OpenAI, OpenRouter, a + local Ollama, or any self-hosted server — plus the model and API key in + **Workspace settings → AI**. The key is encrypted and never leaves the server. ## Roadmap diff --git a/README.ru.md b/README.ru.md index 8d188395..42957cd3 100644 --- a/README.ru.md +++ b/README.ru.md @@ -68,7 +68,7 @@ real-time-коллаборации Docmost, поэтому запись нико **Это тот же сервер, что и отдельный docmost-mcp, — просто встроенный.** Это ровно тот самый [docmost-mcp](https://github.com/vvzvlad/docmost-mcp), который можно запускать и отдельно; от встраивания он не становится «мощнее» — просто не нужно ставить и держать отдельный -процесс. Админ включает его одним переключателем в **Настройки воркспейса → AI & MCP**, а +процесс. Админ включает его одним переключателем в **Настройки воркспейса → AI**, а любой MCP-клиент указывает на `${APP_URL}/mcp`. ### Чат с AI-агентом @@ -89,9 +89,9 @@ real-time-коллаборации Docmost, поэтому запись нико семантический поиск по страницам. - **Доступ в интернет через внешние MCP.** Админ может подключить внешние MCP-серверы (например, Tavily), чтобы дать агенту веб-поиск / доступ в интернет. -- **Своя модель.** Провайдер (OpenAI, Gemini или Ollama), модель и API-ключ настраиваются - в **Настройки воркспейса → AI & MCP → AI / Модели**. Ключ шифруется и никогда не покидает - сервер. +- **Своя модель.** OpenAI-совместимый эндпоинт — OpenAI, OpenRouter, локальный Ollama или + любой self-hosted-сервер — плюс модель и API-ключ настраиваются в + **Настройки воркспейса → AI**. Ключ шифруется и никогда не покидает сервер. ## Дорожная карта diff --git a/apps/client/src/App.tsx b/apps/client/src/App.tsx index accc5cd7..d19bbded 100644 --- a/apps/client/src/App.tsx +++ b/apps/client/src/App.tsx @@ -6,6 +6,7 @@ import Page from "@/pages/page/page"; import AccountSettings from "@/pages/settings/account/account-settings"; import WorkspaceMembers from "@/pages/settings/workspace/workspace-members"; import WorkspaceSettings from "@/pages/settings/workspace/workspace-settings"; +import AiSettings from "@/pages/settings/workspace/ai-settings"; import Groups from "@/pages/settings/group/groups"; import GroupInfo from "./pages/settings/group/group-info"; import Spaces from "@/pages/settings/space/spaces.tsx"; @@ -71,6 +72,7 @@ export default function App() { element={} /> } /> + } /> } /> } /> } /> diff --git a/apps/client/src/components/settings/settings-sidebar.tsx b/apps/client/src/components/settings/settings-sidebar.tsx index 26dbf955..47ecece6 100644 --- a/apps/client/src/components/settings/settings-sidebar.tsx +++ b/apps/client/src/components/settings/settings-sidebar.tsx @@ -9,6 +9,7 @@ import { IconSpaces, IconBrush, IconWorld, + IconSparkles, } from "@tabler/icons-react"; import { Link, useLocation } from "react-router-dom"; import classes from "./settings.module.css"; @@ -52,6 +53,7 @@ const groupedData: DataGroup[] = [ heading: "Workspace", items: [ { label: "General", icon: IconSettings, path: "/settings/workspace" }, + { label: "AI", icon: IconSparkles, path: "/settings/ai" }, { label: "Members", icon: IconUsers, path: "/settings/members" }, { label: "Groups", icon: IconUsersGroup, path: "/settings/groups" }, { label: "Spaces", icon: IconSpaces, path: "/settings/spaces" }, diff --git a/apps/client/src/lib/app-route.ts b/apps/client/src/lib/app-route.ts index ace93caa..ed672b98 100644 --- a/apps/client/src/lib/app-route.ts +++ b/apps/client/src/lib/app-route.ts @@ -17,6 +17,7 @@ const APP_ROUTE = { }, WORKSPACE: { GENERAL: "/settings/workspace", + AI: "/settings/ai", MEMBERS: "/settings/members", GROUPS: "/settings/groups", SPACES: "/settings/spaces", diff --git a/apps/client/src/pages/settings/workspace/ai-settings.tsx b/apps/client/src/pages/settings/workspace/ai-settings.tsx new file mode 100644 index 00000000..aa9e7fb2 --- /dev/null +++ b/apps/client/src/pages/settings/workspace/ai-settings.tsx @@ -0,0 +1,28 @@ +import SettingsTitle from "@/components/settings/settings-title.tsx"; +import McpSettings from "@/features/workspace/components/settings/components/mcp-settings.tsx"; +import AiProviderSettings from "@/features/workspace/components/settings/components/ai-provider-settings.tsx"; +import { useTranslation } from "react-i18next"; +import { getAppName } from "@/lib/config.ts"; +import { Helmet } from "react-helmet-async"; +import { Divider } from "@mantine/core"; +import useUserRole from "@/hooks/use-user-role.tsx"; + +export default function AiSettings() { + const { t } = useTranslation(); + const { isAdmin } = useUserRole(); + return ( + <> + + + {t("AI")} - {getAppName()} + + + + {isAdmin && } + + + + + + ); +} diff --git a/apps/client/src/pages/settings/workspace/workspace-settings.tsx b/apps/client/src/pages/settings/workspace/workspace-settings.tsx index a7130e5a..bb759a9b 100644 --- a/apps/client/src/pages/settings/workspace/workspace-settings.tsx +++ b/apps/client/src/pages/settings/workspace/workspace-settings.tsx @@ -1,17 +1,12 @@ import SettingsTitle from "@/components/settings/settings-title.tsx"; import WorkspaceNameForm from "@/features/workspace/components/settings/components/workspace-name-form"; import WorkspaceIcon from "@/features/workspace/components/settings/components/workspace-icon.tsx"; -import McpSettings from "@/features/workspace/components/settings/components/mcp-settings.tsx"; -import AiProviderSettings from "@/features/workspace/components/settings/components/ai-provider-settings.tsx"; import { useTranslation } from "react-i18next"; import { getAppName } from "@/lib/config.ts"; import { Helmet } from "react-helmet-async"; -import { Divider } from "@mantine/core"; -import useUserRole from "@/hooks/use-user-role.tsx"; export default function WorkspaceSettings() { const { t } = useTranslation(); - const { isAdmin } = useUserRole(); return ( <> @@ -20,15 +15,6 @@ export default function WorkspaceSettings() { - - - - - {isAdmin && } - - - - ); }