refactor(ai): move AI settings to a dedicated /settings/ai page
Extract the AI provider/endpoints settings and the MCP server section out of the Workspace "General" settings page into their own "AI" settings page, reachable from a new sidebar entry. - add page apps/client/.../settings/workspace/ai-settings.tsx (AiProviderSettings admin-gated + McpSettings), with its own Helmet title - register the /settings/ai route in App.tsx and add SETTINGS.WORKSPACE.AI to app-route.ts - add an "AI" item (IconSparkles) to the Workspace group in settings-sidebar - trim workspace-settings.tsx back to the General section and drop the now-unused imports
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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**. Ключ шифруется и никогда не покидает сервер.
|
||||
|
||||
## Дорожная карта
|
||||
|
||||
|
||||
@@ -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={<AccountPreferences />}
|
||||
/>
|
||||
<Route path={"workspace"} element={<WorkspaceSettings />} />
|
||||
<Route path={"ai"} element={<AiSettings />} />
|
||||
<Route path={"members"} element={<WorkspaceMembers />} />
|
||||
<Route path={"groups"} element={<Groups />} />
|
||||
<Route path={"groups/:groupId"} element={<GroupInfo />} />
|
||||
|
||||
@@ -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" },
|
||||
|
||||
@@ -17,6 +17,7 @@ const APP_ROUTE = {
|
||||
},
|
||||
WORKSPACE: {
|
||||
GENERAL: "/settings/workspace",
|
||||
AI: "/settings/ai",
|
||||
MEMBERS: "/settings/members",
|
||||
GROUPS: "/settings/groups",
|
||||
SPACES: "/settings/spaces",
|
||||
|
||||
28
apps/client/src/pages/settings/workspace/ai-settings.tsx
Normal file
28
apps/client/src/pages/settings/workspace/ai-settings.tsx
Normal file
@@ -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 (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>
|
||||
{t("AI")} - {getAppName()}
|
||||
</title>
|
||||
</Helmet>
|
||||
<SettingsTitle title={t("AI")} />
|
||||
{isAdmin && <AiProviderSettings />}
|
||||
|
||||
<Divider my="lg" />
|
||||
|
||||
<McpSettings />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -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 (
|
||||
<>
|
||||
<Helmet>
|
||||
@@ -20,15 +15,6 @@ export default function WorkspaceSettings() {
|
||||
<SettingsTitle title={t("General")} />
|
||||
<WorkspaceIcon />
|
||||
<WorkspaceNameForm />
|
||||
|
||||
<Divider my="lg" />
|
||||
|
||||
<SettingsTitle title={t("AI")} />
|
||||
{isAdmin && <AiProviderSettings />}
|
||||
|
||||
<Divider my="lg" />
|
||||
|
||||
<McpSettings />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user