mirror of
https://github.com/docmost/docmost.git
synced 2026-05-07 14:43:06 +08:00
* enhance ai menu
* remove api prefix from mcp
This commit is contained in:
@@ -614,6 +614,7 @@
|
||||
"AI is only available in the Docmost enterprise edition. Contact sales@docmost.com.": "AI is only available in the Docmost enterprise edition. Contact sales@docmost.com.",
|
||||
"AI & MCP": "AI & MCP",
|
||||
"AI": "AI",
|
||||
"AI settings": "AI settings",
|
||||
"MCP": "MCP",
|
||||
"Model Context Protocol (MCP)": "Model Context Protocol (MCP)",
|
||||
"Enable the MCP server to allow AI assistants and tools to interact with your workspace content.": "Enable the MCP server to allow AI assistants and tools to interact with your workspace content.",
|
||||
|
||||
@@ -113,7 +113,7 @@ const groupedData: DataGroup[] = [
|
||||
showDisabledInNonEE: true,
|
||||
},
|
||||
{
|
||||
label: "AI",
|
||||
label: "AI settings",
|
||||
icon: IconSparkles,
|
||||
path: "/settings/ai",
|
||||
isAdmin: true,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Editor } from "@tiptap/react";
|
||||
import { ActionIcon, TextInput, Tooltip } from "@mantine/core";
|
||||
import { ActionIcon, TextInput } from "@mantine/core";
|
||||
import { useDebouncedCallback, useMediaQuery } from "@mantine/hooks";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
@@ -14,7 +14,7 @@ import { ResultPreview } from "./result-preview.tsx";
|
||||
import classes from "./ai-menu.module.css";
|
||||
import { marked } from "marked";
|
||||
import { DOMSerializer } from "@tiptap/pm/model";
|
||||
import { htmlToMarkdown } from "@docmost/editor-ext";
|
||||
import { copyToClipboard, htmlToMarkdown } from "@docmost/editor-ext";
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
interface EditorAiMenuProps {
|
||||
@@ -110,6 +110,7 @@ const EditorAiMenu = ({ editor }: EditorAiMenuProps): JSX.Element | null => {
|
||||
setOutput((output) => output + chunk.content);
|
||||
},
|
||||
onComplete: () => {
|
||||
setPrompt("");
|
||||
setIsLoading(false);
|
||||
setActiveCommandSet("result");
|
||||
},
|
||||
@@ -146,13 +147,18 @@ const EditorAiMenu = ({ editor }: EditorAiMenuProps): JSX.Element | null => {
|
||||
}
|
||||
|
||||
const html = (marked.parse(output) as string).trim();
|
||||
// Strip <p> wrapper for single-paragraph output to preserve inline context
|
||||
const content =
|
||||
const isSingleParagraph =
|
||||
html.startsWith("<p>") &&
|
||||
html.endsWith("</p>") &&
|
||||
html.lastIndexOf("<p>") === 0
|
||||
? html.slice(3, -4)
|
||||
: html;
|
||||
html.lastIndexOf("<p>") === 0;
|
||||
|
||||
// Strip <p> wrapper for single-paragraph output to preserve inline context,
|
||||
// then decode HTML entities via DOMParser since TipTap would otherwise
|
||||
// treat the tagless string as plain text and insert entities literally.
|
||||
const content = isSingleParagraph
|
||||
? new DOMParser().parseFromString(html.slice(3, -4), "text/html")
|
||||
.body.innerHTML
|
||||
: html;
|
||||
|
||||
chain.insertContent(content).run();
|
||||
|
||||
@@ -169,7 +175,7 @@ const EditorAiMenu = ({ editor }: EditorAiMenuProps): JSX.Element | null => {
|
||||
return setShowAiMenu(false);
|
||||
}
|
||||
if (item.id === "result-copy") {
|
||||
navigator.clipboard.writeText(output);
|
||||
copyToClipboard(output);
|
||||
|
||||
return setShowAiMenu(false);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ export default function McpSettings() {
|
||||
const [checked, setChecked] = useState(workspace?.settings?.ai?.mcp);
|
||||
const hasAccess = useIsCloudEE();
|
||||
|
||||
const mcpUrl = `${getAppUrl()}/api/mcp`;
|
||||
const mcpUrl = `${getAppUrl()}/mcp`;
|
||||
|
||||
const handleChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = event.currentTarget.checked;
|
||||
|
||||
@@ -37,9 +37,9 @@ export default function AiSettings() {
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>AI - {getAppName()}</title>
|
||||
<title>AI settings - {getAppName()}</title>
|
||||
</Helmet>
|
||||
<SettingsTitle title={t("AI")} />
|
||||
<SettingsTitle title={t("AI settings")} />
|
||||
|
||||
<Tabs color="dark" value={activeTab} onChange={handleTabChange}>
|
||||
<Tabs.List>
|
||||
|
||||
@@ -77,7 +77,7 @@ export default function UserApiKeys() {
|
||||
<Text size="sm" mt={4}>
|
||||
{t("MCP server URL:")}{" "}
|
||||
<Text size="sm" fw={500} span ff="monospace">
|
||||
{`${getAppUrl()}/api/mcp`}
|
||||
{`${getAppUrl()}/mcp`}
|
||||
</Text>
|
||||
</Text>
|
||||
</Alert>
|
||||
|
||||
@@ -36,7 +36,7 @@ async function bootstrap() {
|
||||
app.useLogger(app.get(PinoLogger));
|
||||
|
||||
app.setGlobalPrefix('api', {
|
||||
exclude: ['robots.txt', 'share/:shareId/p/:pageSlug'],
|
||||
exclude: ['robots.txt', 'share/:shareId/p/:pageSlug', 'mcp'],
|
||||
});
|
||||
|
||||
const reflector = app.get(Reflector);
|
||||
|
||||
Reference in New Issue
Block a user