diff --git a/apps/client/public/locales/de-DE/translation.json b/apps/client/public/locales/de-DE/translation.json index 0368ad42..50a23634 100644 --- a/apps/client/public/locales/de-DE/translation.json +++ b/apps/client/public/locales/de-DE/translation.json @@ -665,9 +665,6 @@ "AI-powered search (AI Answers)": "KI-unterstützte Suche (KI-Antworten)", "AI search uses vector embeddings to provide semantic search capabilities across your workspace content.": "Die KI-Suche verwendet Vektor-Einbettungen, um semantische Suchfunktionen in Ihrem Arbeitsbereich bereitzustellen.", "Toggle AI search": "KI-Suche umschalten", - "Generative AI (Ask AI)": "Generative KI (KI fragen)", - "Enable AI-powered content generation in the editor. Allows users to generate, improve, translate and transform text.": "Aktivieren Sie die KI-unterstützte Inhaltserstellung im Editor. Ermöglicht Benutzern das Erzeugen, Verbessern, Übersetzen und Transformieren von Text.", - "Toggle generative AI": "Generative KI umschalten", "Upgrade your plan": "Upgrade Ihres Plans", "Available with a paid license": "Verfügbar mit einer kostenpflichtigen Lizenz", "Upgrade your license tier.": "Stufen Sie Ihre Lizenz hoch.", diff --git a/apps/client/public/locales/en-US/translation.json b/apps/client/public/locales/en-US/translation.json index 903e169f..95fd4d28 100644 --- a/apps/client/public/locales/en-US/translation.json +++ b/apps/client/public/locales/en-US/translation.json @@ -687,9 +687,6 @@ "AI-powered search (AI Answers)": "AI-powered search (AI Answers)", "AI search uses vector embeddings to provide semantic search capabilities across your workspace content.": "AI search uses vector embeddings to provide semantic search capabilities across your workspace content.", "Toggle AI search": "Toggle AI search", - "Generative AI (Ask AI)": "Generative AI (Ask AI)", - "Enable AI-powered content generation in the editor. Allows users to generate, improve, translate and transform text.": "Enable AI-powered content generation in the editor. Allows users to generate, improve, translate and transform text.", - "Toggle generative AI": "Toggle generative AI", "Upgrade your plan": "Upgrade your plan", "Available with a paid license": "Available with a paid license", "Upgrade your license tier.": "Upgrade your license tier.", diff --git a/apps/client/public/locales/es-ES/translation.json b/apps/client/public/locales/es-ES/translation.json index 13197773..420e731a 100644 --- a/apps/client/public/locales/es-ES/translation.json +++ b/apps/client/public/locales/es-ES/translation.json @@ -665,9 +665,6 @@ "AI-powered search (AI Answers)": "Búsqueda impulsada por IA (Respuestas de IA)", "AI search uses vector embeddings to provide semantic search capabilities across your workspace content.": "La búsqueda de IA utiliza incrustaciones vectoriales para proporcionar capacidades de búsqueda semántica en todo el contenido de su espacio de trabajo.", "Toggle AI search": "Alternar búsqueda de IA", - "Generative AI (Ask AI)": "IA generativa (Preguntar a la IA)", - "Enable AI-powered content generation in the editor. Allows users to generate, improve, translate and transform text.": "Habilitar la generación de contenido impulsada por IA en el editor. Permite a los usuarios generar, mejorar, traducir y transformar texto.", - "Toggle generative AI": "Activar IA generativa", "Upgrade your plan": "Mejora tu plan", "Available with a paid license": "Disponible con una licencia de pago", "Upgrade your license tier.": "Mejora el nivel de tu licencia.", diff --git a/apps/client/public/locales/fr-FR/translation.json b/apps/client/public/locales/fr-FR/translation.json index 20f35442..9b59c7fe 100644 --- a/apps/client/public/locales/fr-FR/translation.json +++ b/apps/client/public/locales/fr-FR/translation.json @@ -665,9 +665,6 @@ "AI-powered search (AI Answers)": "Recherche propulsée par IA (Réponses IA)", "AI search uses vector embeddings to provide semantic search capabilities across your workspace content.": "La recherche IA utilise des incorporations vectorielles pour fournir des capacités de recherche sémantique à travers le contenu de votre espace de travail.", "Toggle AI search": "Basculer la recherche IA", - "Generative AI (Ask AI)": "IA générative (Demandez à l'IA)", - "Enable AI-powered content generation in the editor. Allows users to generate, improve, translate and transform text.": "Activer la génération de contenu assistée par IA dans l'éditeur. Permet aux utilisateurs de générer, améliorer, traduire et transformer du texte.", - "Toggle generative AI": "Activer/désactiver l'IA générative", "Upgrade your plan": "Mettez à niveau votre forfait", "Available with a paid license": "Disponible avec une licence payante", "Upgrade your license tier.": "Mettez à niveau votre niveau de licence.", diff --git a/apps/client/public/locales/it-IT/translation.json b/apps/client/public/locales/it-IT/translation.json index 441c90f6..01d56f76 100644 --- a/apps/client/public/locales/it-IT/translation.json +++ b/apps/client/public/locales/it-IT/translation.json @@ -665,9 +665,6 @@ "AI-powered search (AI Answers)": "Ricerca con AI (Risposte AI)", "AI search uses vector embeddings to provide semantic search capabilities across your workspace content.": "La ricerca AI utilizza embeddings vettoriali per fornire capacità di ricerca semantica nel contenuto della tua area di lavoro.", "Toggle AI search": "Attiva/disattiva ricerca AI", - "Generative AI (Ask AI)": "AI generativa (Chiedi AI)", - "Enable AI-powered content generation in the editor. Allows users to generate, improve, translate and transform text.": "Abilita la generazione di contenuti con AI nell'editor. Consente agli utenti di generare, migliorare, tradurre e trasformare il testo.", - "Toggle generative AI": "Attiva/Disattiva AI generativa", "Upgrade your plan": "Aggiorna il tuo piano", "Available with a paid license": "Disponibile con una licenza a pagamento", "Upgrade your license tier.": "Aggiorna il livello della tua licenza.", diff --git a/apps/client/public/locales/ja-JP/translation.json b/apps/client/public/locales/ja-JP/translation.json index 492868cf..92451055 100644 --- a/apps/client/public/locales/ja-JP/translation.json +++ b/apps/client/public/locales/ja-JP/translation.json @@ -665,9 +665,6 @@ "AI-powered search (AI Answers)": "AI搭載検索 (AI回答)", "AI search uses vector embeddings to provide semantic search capabilities across your workspace content.": "AI検索はベクター埋め込みを使用してワークスペース全体の意味検索を実現します", "Toggle AI search": "AI検索を切り替え", - "Generative AI (Ask AI)": "生成AI (Ask AI)", - "Enable AI-powered content generation in the editor. Allows users to generate, improve, translate and transform text.": "エディターでAIを活用したコンテンツ生成を有効にします。ユーザーがテキストの生成、改善、翻訳、および変換を行うことができます。", - "Toggle generative AI": "生成AIを切り替える", "Upgrade your plan": "プランをアップグレードする", "Available with a paid license": "有料ライセンスで利用可能", "Upgrade your license tier.": "ライセンスタイアをアップグレードしてください。", diff --git a/apps/client/public/locales/ko-KR/translation.json b/apps/client/public/locales/ko-KR/translation.json index 5847ab19..d6c8ee35 100644 --- a/apps/client/public/locales/ko-KR/translation.json +++ b/apps/client/public/locales/ko-KR/translation.json @@ -665,9 +665,6 @@ "AI-powered search (AI Answers)": "AI 구동 검색 (AI 답변)", "AI search uses vector embeddings to provide semantic search capabilities across your workspace content.": "AI 검색은 벡터 임베딩을 사용하여 작업공간 콘텐츠에 대한 의미 검색 기능을 제공합니다.", "Toggle AI search": "AI 검색 전환", - "Generative AI (Ask AI)": "생성 AI (Ask AI)", - "Enable AI-powered content generation in the editor. Allows users to generate, improve, translate and transform text.": "편집기에서 AI 구동 콘텐츠 생성을 활성화합니다. 사용자가 텍스트를 생성, 개선, 번역 및 변환할 수 있습니다.", - "Toggle generative AI": "생성 AI 토글", "Upgrade your plan": "요금제를 업그레이드하세요", "Available with a paid license": "유료 라이선스에서만 사용 가능합니다", "Upgrade your license tier.": "라이선스 등급을 업그레이드하세요.", diff --git a/apps/client/public/locales/nl-NL/translation.json b/apps/client/public/locales/nl-NL/translation.json index 591c9674..5c0ea08b 100644 --- a/apps/client/public/locales/nl-NL/translation.json +++ b/apps/client/public/locales/nl-NL/translation.json @@ -665,9 +665,6 @@ "AI-powered search (AI Answers)": "AI-gestuurde zoekopdracht (AI Antwoorden)", "AI search uses vector embeddings to provide semantic search capabilities across your workspace content.": "AI-zoekopdracht maakt gebruik van vectorembeddings om semantische zoekmogelijkheden te bieden in uw werkruimte-inhoud.", "Toggle AI search": "Schakel AI-zoekopdracht in/uit", - "Generative AI (Ask AI)": "Generatieve AI (Vraag het AI)", - "Enable AI-powered content generation in the editor. Allows users to generate, improve, translate and transform text.": "Schakel AI-gestuurde inhoudsgeneratie in de editor in. Hiermee kunnen gebruikers tekst genereren, verbeteren, vertalen en transformeren.", - "Toggle generative AI": "Generatieve AI schakelen", "Upgrade your plan": "Upgrade je abonnement", "Available with a paid license": "Beschikbaar met een betaalde licentie", "Upgrade your license tier.": "Upgrade je licentieniveau.", diff --git a/apps/client/public/locales/pt-BR/translation.json b/apps/client/public/locales/pt-BR/translation.json index e2788f1f..bdcf7c49 100644 --- a/apps/client/public/locales/pt-BR/translation.json +++ b/apps/client/public/locales/pt-BR/translation.json @@ -665,9 +665,6 @@ "AI-powered search (AI Answers)": "Pesquisa com IA (Respostas de IA)", "AI search uses vector embeddings to provide semantic search capabilities across your workspace content.": "A pesquisa IA usa vetores de incorporação para fornecer capacidades de pesquisa semântica em todo o conteúdo do seu espaço de trabalho.", "Toggle AI search": "Alternar pesquisa de IA", - "Generative AI (Ask AI)": "IA generativa (Perguntar à IA)", - "Enable AI-powered content generation in the editor. Allows users to generate, improve, translate and transform text.": "Habilitar geração de conteúdo com IA no editor. Permite aos usuários gerar, melhorar, traduzir e transformar texto.", - "Toggle generative AI": "Alternar IA generativa", "Upgrade your plan": "Faça upgrade do seu plano", "Available with a paid license": "Disponível com uma licença paga", "Upgrade your license tier.": "Faça upgrade do seu nível de licença.", diff --git a/apps/client/public/locales/ru-RU/translation.json b/apps/client/public/locales/ru-RU/translation.json index aa118677..dc74cd7f 100644 --- a/apps/client/public/locales/ru-RU/translation.json +++ b/apps/client/public/locales/ru-RU/translation.json @@ -749,9 +749,6 @@ "AI-powered search (AI Answers)": "Поиск на базе ИИ (Ответы ИИ)", "AI search uses vector embeddings to provide semantic search capabilities across your workspace content.": "Поиск ИИ использует векторные встраивания для обеспечения семантического поиска по содержимому вашего рабочего пространства.", "Toggle AI search": "Переключить поиск ИИ", - "Generative AI (Ask AI)": "Генеративный ИИ (Спросить ИИ)", - "Enable AI-powered content generation in the editor. Allows users to generate, improve, translate and transform text.": "Включите создание контента на базе ИИ в редакторе. Позволяет пользователям генерировать, улучшать, переводить и преобразовывать текст.", - "Toggle generative AI": "Переключить генеративный ИИ", "Upgrade your plan": "Обновите свой тарифный план", "Available with a paid license": "Доступно с платной лицензией", "Upgrade your license tier.": "Обновите уровень вашей лицензии.", diff --git a/apps/client/public/locales/uk-UA/translation.json b/apps/client/public/locales/uk-UA/translation.json index 6144df46..8f31b49e 100644 --- a/apps/client/public/locales/uk-UA/translation.json +++ b/apps/client/public/locales/uk-UA/translation.json @@ -665,9 +665,6 @@ "AI-powered search (AI Answers)": "Пошук на базі ШІ (Відповіді ШІ)", "AI search uses vector embeddings to provide semantic search capabilities across your workspace content.": "Пошук з ШІ використовує векторні вбудовування для надання можливостей семантичного пошуку у вашому робочому вмісті.", "Toggle AI search": "Переключити пошук з ШІ", - "Generative AI (Ask AI)": "Генеративний ШІ (Запитати ШІ)", - "Enable AI-powered content generation in the editor. Allows users to generate, improve, translate and transform text.": "Увімкнути генерацію контенту за допомогою ШІ в редакторі. Дозволяє користувачам генерувати, покращувати, перекладати та трансформувати текст.", - "Toggle generative AI": "Переключити генеративний ШІ", "Upgrade your plan": "Оновіть свій тарифний план", "Available with a paid license": "Доступно за платною ліцензією", "Upgrade your license tier.": "Оновіть рівень своєї ліцензії.", diff --git a/apps/client/public/locales/zh-CN/translation.json b/apps/client/public/locales/zh-CN/translation.json index 40cd5c1b..c09e6502 100644 --- a/apps/client/public/locales/zh-CN/translation.json +++ b/apps/client/public/locales/zh-CN/translation.json @@ -665,9 +665,6 @@ "AI-powered search (AI Answers)": "AI驱动的搜索 (AI答案)", "AI search uses vector embeddings to provide semantic search capabilities across your workspace content.": "AI搜索使用向量嵌入提供跨工作空间内容的语义搜索功能。", "Toggle AI search": "切换AI搜索", - "Generative AI (Ask AI)": "生成型AI (询问AI)", - "Enable AI-powered content generation in the editor. Allows users to generate, improve, translate and transform text.": "在编辑器中启用AI驱动的内容生成。允许用户生成、改进、翻译和转换文本。", - "Toggle generative AI": "切换生成型AI", "Upgrade your plan": "升级您的方案", "Available with a paid license": "需付费许可才可用", "Upgrade your license tier.": "升级您的许可等级。", diff --git a/apps/client/src/features/editor/atoms/editor-atoms.ts b/apps/client/src/features/editor/atoms/editor-atoms.ts index c0873adf..8d225165 100644 --- a/apps/client/src/features/editor/atoms/editor-atoms.ts +++ b/apps/client/src/features/editor/atoms/editor-atoms.ts @@ -10,8 +10,6 @@ export const readOnlyEditorAtom = atom(null); export const yjsConnectionStatusAtom = atom(""); -export const showAiMenuAtom = atom(false); - export const showLinkMenuAtom = atom(false); // Current page's edit mode — initialized from the user's saved preference on diff --git a/apps/client/src/features/editor/components/bubble-menu/bubble-menu.tsx b/apps/client/src/features/editor/components/bubble-menu/bubble-menu.tsx index 5ad966af..5c590487 100644 --- a/apps/client/src/features/editor/components/bubble-menu/bubble-menu.tsx +++ b/apps/client/src/features/editor/components/bubble-menu/bubble-menu.tsx @@ -9,11 +9,10 @@ import { IconStrikethrough, IconUnderline, IconMessage, - IconSparkles, } from "@tabler/icons-react"; import clsx from "clsx"; import classes from "./bubble-menu.module.css"; -import { ActionIcon, Button, rem, Tooltip } from "@mantine/core"; +import { ActionIcon, rem, Tooltip } from "@mantine/core"; import { ColorSelector } from "./color-selector"; import { NodeSelector } from "./node-selector"; import { TextAlignmentSelector } from "./text-alignment-selector"; @@ -26,8 +25,8 @@ import { v7 as uuid7 } from "uuid"; import { isCellSelection, isTextSelected } from "@docmost/editor-ext"; import { LinkSelector } from "@/features/editor/components/bubble-menu/link-selector.tsx"; import { useTranslation } from "react-i18next"; -import { showAiMenuAtom, showLinkMenuAtom } from "@/features/editor/atoms/editor-atoms"; -import { userAtom, workspaceAtom } from "@/features/user/atoms/current-user-atom"; +import { showLinkMenuAtom } from "@/features/editor/atoms/editor-atoms"; +import { userAtom } from "@/features/user/atoms/current-user-atom"; export interface BubbleMenuItem { name: string; @@ -44,16 +43,12 @@ type EditorBubbleMenuProps = Omit & { export const EditorBubbleMenu: FC = (props) => { const { templateMode = false } = props; const { t } = useTranslation(); - const [showAiMenu, setShowAiMenu] = useAtom(showAiMenuAtom); const [showCommentPopup, setShowCommentPopup] = useAtom(showCommentPopupAtom); - const workspace = useAtomValue(workspaceAtom); - const isGenerativeAiEnabled = workspace?.settings?.ai?.generative === true; const user = useAtomValue(userAtom); const editorToolbarEnabled = user?.settings?.preferences?.editorToolbar ?? false; const [, setDraftCommentId] = useAtom(draftCommentIdAtom); const showCommentPopupRef = useRef(showCommentPopup); - const showAiMenuRef = useRef(showAiMenu); const [showLinkMenu] = useAtom(showLinkMenuAtom); const showLinkMenuRef = useRef(showLinkMenu); @@ -61,10 +56,6 @@ export const EditorBubbleMenu: FC = (props) => { showCommentPopupRef.current = showCommentPopup; }, [showCommentPopup]); - useEffect(() => { - showAiMenuRef.current = showAiMenu; - }, [showAiMenu]); - useEffect(() => { showLinkMenuRef.current = showLinkMenu; }, [showLinkMenu]); @@ -145,7 +136,6 @@ export const EditorBubbleMenu: FC = (props) => { empty || isNodeSelection(selection) || isCellSelection(selection) || - showAiMenuRef.current || showLinkMenuRef.current || showCommentPopupRef?.current ) { @@ -168,8 +158,8 @@ export const EditorBubbleMenu: FC = (props) => { const [isTextAlignmentSelectorOpen, setIsTextAlignmentOpen] = useState(false); const [isColorSelectorOpen, setIsColorSelectorOpen] = useState(false); - // Hide the bubble menu immediately when AI menu is shown - if (showAiMenu || showLinkMenu) return; + // Hide the bubble menu immediately when the link menu is shown + if (showLinkMenu) return; return ( = (props) => { style={{ zIndex: 199, position: "relative" }} >
- {isGenerativeAiEnabled && ( - <> - -
- - )} {!editorToolbarEnabled && ( <> = ({ const editorFromAtom = useAtomValue(pageEditorAtom); const editor = editorProp ?? editorFromAtom; const state = useToolbarState(editor); - const workspace = useAtomValue(workspaceAtom); - const isGenerativeAiEnabled = workspace?.settings?.ai?.generative === true; if (!editor || !state) return null; @@ -43,12 +39,6 @@ export const FixedToolbar: FC = ({ onMouseDown={(e) => e.preventDefault()} >
- {/* {isGenerativeAiEnabled && ( - <> - -
- - )} */}
diff --git a/apps/client/src/features/editor/components/fixed-toolbar/groups/ask-ai-group.tsx b/apps/client/src/features/editor/components/fixed-toolbar/groups/ask-ai-group.tsx deleted file mode 100644 index 48b95cd2..00000000 --- a/apps/client/src/features/editor/components/fixed-toolbar/groups/ask-ai-group.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { FC } from "react"; -import { Button } from "@mantine/core"; -import { IconSparkles } from "@tabler/icons-react"; -import { useSetAtom } from "jotai"; -import { useTranslation } from "react-i18next"; -import { showAiMenuAtom } from "@/features/editor/atoms/editor-atoms"; - -export const AskAiGroup: FC = () => { - const { t } = useTranslation(); - const setShowAiMenu = useSetAtom(showAiMenuAtom); - - return ( - - ); -}; diff --git a/apps/client/src/features/editor/components/fixed-toolbar/groups/generate-title-group.tsx b/apps/client/src/features/editor/components/fixed-toolbar/groups/generate-title-group.tsx index b191c426..36746be4 100644 --- a/apps/client/src/features/editor/components/fixed-toolbar/groups/generate-title-group.tsx +++ b/apps/client/src/features/editor/components/fixed-toolbar/groups/generate-title-group.tsx @@ -13,7 +13,7 @@ interface Props { /** * AI "generate title" button (#199). Reads the live editor content and applies a * model-suggested title immediately. Rendered in the page byline, only in edit - * mode and when the workspace's generative AI flag is on. + * mode and when the workspace's AI chat flag is on. */ export const GenerateTitleGroup: FC = ({ pageId, diff --git a/apps/client/src/features/editor/full-editor.tsx b/apps/client/src/features/editor/full-editor.tsx index 53b3ba08..cc597688 100644 --- a/apps/client/src/features/editor/full-editor.tsx +++ b/apps/client/src/features/editor/full-editor.tsx @@ -77,9 +77,9 @@ export function FullEditor({ const [user] = useAtom(userAtom); const workspace = useAtomValue(workspaceAtom); const isDictationEnabled = workspace?.settings?.ai?.dictation === true; - // AI title generation reuses the generative AI flag (same gate as the on-page - // generative menu); the server enforces it too (#199). - const isTitleGenEnabled = workspace?.settings?.ai?.generative === true; + // AI title generation is gated by the general AI chat flag (the same toggle + // that enables the chat agent); the server enforces it too (#199). + const isTitleGenEnabled = workspace?.settings?.ai?.chat === true; const fullPageWidth = user.settings?.preferences?.fullPageWidth; const editorToolbarEnabled = user.settings?.preferences?.editorToolbar ?? false; @@ -254,7 +254,7 @@ function PageByline({ {showDictation && editor && ( )} - {/* Shown only in edit mode when the workspace's generative AI flag is on, + {/* Shown only in edit mode when the workspace's AI chat flag is on, so AI title generation stays reachable from the byline (#199). */} {showTitleGen && ( diff --git a/apps/client/src/features/workspace/types/workspace.types.ts b/apps/client/src/features/workspace/types/workspace.types.ts index 18faf12e..99824db6 100644 --- a/apps/client/src/features/workspace/types/workspace.types.ts +++ b/apps/client/src/features/workspace/types/workspace.types.ts @@ -20,7 +20,6 @@ export interface IWorkspace { plan?: string; enforceMfa?: boolean; aiSearch?: boolean; - generativeAi?: boolean; disablePublicSharing?: boolean; mcpEnabled?: boolean; aiChat?: boolean; @@ -61,7 +60,6 @@ export interface IWorkspaceApiSettings { export interface IWorkspaceAiSettings { search?: boolean; - generative?: boolean; mcp?: boolean; chat?: boolean; dictation?: boolean; diff --git a/apps/server/src/core/ai-chat/ai-chat.controller.ts b/apps/server/src/core/ai-chat/ai-chat.controller.ts index da09c340..87bf7ec6 100644 --- a/apps/server/src/core/ai-chat/ai-chat.controller.ts +++ b/apps/server/src/core/ai-chat/ai-chat.controller.ts @@ -319,8 +319,8 @@ export class AiChatController { /** * Generate a page title from supplied note content (#199). One-shot, - * non-streaming. Gated by the workspace AI flag (reusing settings.ai.generative, - * the same flag that gates the on-page generative AI menu); returns { title }. + * non-streaming. Gated by the AI chat flag (settings.ai.chat, the same toggle + * that enables the chat agent); returns { title }. * The endpoint NEVER writes the page — the client applies the title via the * existing /pages/update route (which enforces edit permission), so access * checks are not duplicated here. Throttled per user via AI_CHAT_THROTTLER. @@ -334,9 +334,9 @@ export class AiChatController { @AuthWorkspace() workspace: Workspace, ): Promise<{ title: string }> { const settings = (workspace.settings ?? {}) as { - ai?: { generative?: boolean }; + ai?: { chat?: boolean }; }; - if (settings.ai?.generative !== true) { + if (settings.ai?.chat !== true) { throw new ForbiddenException('AI title generation is disabled'); } try { diff --git a/apps/server/src/core/ai-chat/ai-chat.generate-page-title.spec.ts b/apps/server/src/core/ai-chat/ai-chat.generate-page-title.spec.ts index 08d5bbc9..ef242fdf 100644 --- a/apps/server/src/core/ai-chat/ai-chat.generate-page-title.spec.ts +++ b/apps/server/src/core/ai-chat/ai-chat.generate-page-title.spec.ts @@ -42,7 +42,7 @@ describe('cleanGeneratedTitle', () => { /** * Wiring spec for the #199 `POST /ai-chat/generate-page-title` endpoint. It must: - * gate on settings.ai.generative (403 when off), delegate to the service when on, + * gate on settings.ai.chat (403 when off), delegate to the service when on, * rethrow HttpExceptions verbatim (e.g. AiNotConfiguredException -> 503), and map * any other provider/transport fault to a 503. Exercised by instantiating the * controller with hand-rolled mocks — no Nest graph, no DB. @@ -50,7 +50,7 @@ describe('cleanGeneratedTitle', () => { describe('AiChatController.generatePageTitle', () => { const enabledWorkspace = { id: 'ws1', - settings: { ai: { generative: true } }, + settings: { ai: { chat: true } }, } as unknown as Workspace; function makeController(generate: jest.Mock) { @@ -64,7 +64,7 @@ describe('AiChatController.generatePageTitle', () => { return { controller, aiChatService }; } - it('forbids when the generative AI flag is off', async () => { + it('forbids when the AI chat flag is off', async () => { const generate = jest.fn(); const { controller } = makeController(generate); const disabled = { id: 'ws1', settings: {} } as unknown as Workspace; @@ -74,12 +74,12 @@ describe('AiChatController.generatePageTitle', () => { expect(generate).not.toHaveBeenCalled(); }); - it('forbids when settings.ai.generative is anything but exactly true', async () => { + it('forbids when settings.ai.chat is anything but exactly true', async () => { const generate = jest.fn(); const { controller } = makeController(generate); const ws = { id: 'ws1', - settings: { ai: { generative: 'yes' } }, + settings: { ai: { chat: 'yes' } }, } as unknown as Workspace; await expect( controller.generatePageTitle({ content: 'body' }, ws), diff --git a/apps/server/src/core/workspace/dto/update-workspace.dto.ts b/apps/server/src/core/workspace/dto/update-workspace.dto.ts index 9f0fa3b8..a7d91ca4 100644 --- a/apps/server/src/core/workspace/dto/update-workspace.dto.ts +++ b/apps/server/src/core/workspace/dto/update-workspace.dto.ts @@ -31,10 +31,6 @@ export class UpdateWorkspaceDto extends PartialType(CreateWorkspaceDto) { @IsBoolean() aiSearch: boolean; - @IsOptional() - @IsBoolean() - generativeAi: boolean; - @IsOptional() @IsBoolean() disablePublicSharing: boolean; diff --git a/apps/server/src/core/workspace/services/workspace.service.ts b/apps/server/src/core/workspace/services/workspace.service.ts index f73ec351..14c1ea88 100644 --- a/apps/server/src/core/workspace/services/workspace.service.ts +++ b/apps/server/src/core/workspace/services/workspace.service.ts @@ -145,7 +145,7 @@ export class WorkspaceService { status = WorkspaceStatus.Active; plan = 'standard'; billingEmail = user.email; - settings = { ai: { generative: true, chat: true } }; + settings = { ai: { chat: true } }; } // create workspace @@ -439,20 +439,6 @@ export class WorkspaceService { ); } - if (typeof updateWorkspaceDto.generativeAi !== 'undefined') { - const prev = settingsBefore?.ai?.generative ?? false; - if (prev !== updateWorkspaceDto.generativeAi) { - before.generativeAi = prev; - after.generativeAi = updateWorkspaceDto.generativeAi; - } - await this.workspaceRepo.updateAiSettings( - workspaceId, - 'generative', - updateWorkspaceDto.generativeAi, - trx, - ); - } - if (typeof updateWorkspaceDto.disablePublicSharing !== 'undefined') { const prev = settingsBefore?.sharing?.disabled ?? false; if (prev !== updateWorkspaceDto.disablePublicSharing) { @@ -587,7 +573,6 @@ export class WorkspaceService { delete updateWorkspaceDto.restrictApiToAdmins; delete updateWorkspaceDto.aiSearch; - delete updateWorkspaceDto.generativeAi; delete updateWorkspaceDto.disablePublicSharing; delete updateWorkspaceDto.mcpEnabled; delete updateWorkspaceDto.allowMemberTemplates; diff --git a/apps/server/src/database/repos/workspace/workspace.repo.ts b/apps/server/src/database/repos/workspace/workspace.repo.ts index a3d14099..23ebcc67 100644 --- a/apps/server/src/database/repos/workspace/workspace.repo.ts +++ b/apps/server/src/database/repos/workspace/workspace.repo.ts @@ -246,7 +246,7 @@ export class WorkspaceRepo { * otherwise re-serialize a `JSON.stringify`'d string, yielding a jsonb string * that `||` turns into an array). A `jsonb_typeof = 'object'` CASE self-heals * workspaces whose `settings.ai.provider` was previously corrupted into an - * array/string. Sibling `settings.ai.*` keys (search / generative / chat / mcp + * array/string. Sibling `settings.ai.*` keys (search / chat / mcp * / systemPrompt) and provider fields absent from the partial are preserved via * jsonb `||` merge. */