From 57f951a7d92b6565008d07233bace6aa2eabbb3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samy=20Pess=C3=A9?= Date: Wed, 2 Jul 2025 08:40:55 +0200 Subject: [PATCH] Remove AI page link summaries (#3418) --- .../AIPageLinkSummary/AIPageLinkSummary.tsx | 190 ------------------ .../src/components/AIPageLinkSummary/index.ts | 1 - .../AIPageLinkSummary/server-actions/index.ts | 1 - .../server-actions/streamLinkPageSummary.ts | 157 --------------- .../DocumentView/InlineLink/InlineLink.tsx | 26 --- .../InlineLink/InlineLinkTooltip.tsx | 1 - .../InlineLink/InlineLinkTooltipImpl.tsx | 21 +- packages/gitbook/src/intl/translations/de.ts | 2 - packages/gitbook/src/intl/translations/en.ts | 2 - packages/gitbook/src/intl/translations/es.ts | 2 - packages/gitbook/src/intl/translations/fr.ts | 2 - packages/gitbook/src/intl/translations/ja.ts | 3 - packages/gitbook/src/intl/translations/nl.ts | 2 - packages/gitbook/src/intl/translations/no.ts | 2 - .../gitbook/src/intl/translations/pt-br.ts | 2 - packages/gitbook/src/intl/translations/zh.ts | 2 - 16 files changed, 2 insertions(+), 414 deletions(-) delete mode 100644 packages/gitbook/src/components/AIPageLinkSummary/AIPageLinkSummary.tsx delete mode 100644 packages/gitbook/src/components/AIPageLinkSummary/index.ts delete mode 100644 packages/gitbook/src/components/AIPageLinkSummary/server-actions/index.ts delete mode 100644 packages/gitbook/src/components/AIPageLinkSummary/server-actions/streamLinkPageSummary.ts diff --git a/packages/gitbook/src/components/AIPageLinkSummary/AIPageLinkSummary.tsx b/packages/gitbook/src/components/AIPageLinkSummary/AIPageLinkSummary.tsx deleted file mode 100644 index 85cb590b4..000000000 --- a/packages/gitbook/src/components/AIPageLinkSummary/AIPageLinkSummary.tsx +++ /dev/null @@ -1,190 +0,0 @@ -'use client'; -import { useLanguage } from '@/intl/client'; -import { t } from '@/intl/translate'; -import { Icon } from '@gitbook/icons'; -import { useEffect } from 'react'; -import { create } from 'zustand'; -import { useShallow } from 'zustand/react/shallow'; -import { usePageContext } from '../PageContext'; -import { useVisitedPages } from '../hooks'; -import { Loading } from '../primitives'; -import { streamLinkPageSummary } from './server-actions/streamLinkPageSummary'; - -/** - * Get a unique cache key for a page summary - */ -function getCacheKey(targetSpaceId: string, targetPageId: string): string { - return `${targetSpaceId}:${targetPageId}`; -} - -/** - * Global state for the summaries. - */ -const useSummaries = create<{ - /** - * Cache of all summaries generated so far. - */ - cache: Map; - - /** - * Get a summary for a page. - */ - getSummary: (params: { targetSpaceId: string; targetPageId: string }) => string; - - /** - * Stream the generation of a summary for a page. - */ - streamSummary: (params: { - currentSpaceId: string; - currentPageId: string; - currentPageTitle: string; - targetSpaceId: string; - targetPageId: string; - linkPreview?: string; - linkTitle?: string; - visitedPages: { spaceId: string; pageId: string }[]; - }) => Promise; -}>((set, get) => ({ - cache: new Map(), - - getSummary: ({ - targetSpaceId, - targetPageId, - }: { - targetSpaceId: string; - targetPageId: string; - }) => { - return get().cache.get(getCacheKey(targetSpaceId, targetPageId)) ?? ''; - }, - - streamSummary: async ({ - currentSpaceId, - currentPageId, - currentPageTitle, - targetSpaceId, - targetPageId, - linkPreview, - linkTitle, - visitedPages, - }) => { - const cacheKey = getCacheKey(targetSpaceId, targetPageId); - - if (get().cache.has(cacheKey)) { - // Already generated or generating - return; - } - - const update = (summary: string) => { - set((prev) => { - const newCache = new Map(prev.cache); - newCache.set(cacheKey, summary); - return { cache: newCache }; - }); - }; - - update(''); - const stream = await streamLinkPageSummary({ - currentSpaceId, - currentPageId, - currentPageTitle, - targetSpaceId, - targetPageId, - linkPreview, - linkTitle, - visitedPages, - }); - - let generatedSummary = ''; - for await (const highlight of stream) { - generatedSummary = highlight ?? ''; - update(generatedSummary); - } - }, -})); - -/** - * Summarise a page's content for use in a link preview - */ -export function AIPageLinkSummary(props: { - targetSpaceId: string; - targetPageId: string; - linkPreview?: string; - linkTitle?: string; - showTrademark: boolean; -}) { - const { targetSpaceId, targetPageId, linkPreview, linkTitle, showTrademark = true } = props; - - const currentPage = usePageContext(); - const language = useLanguage(); - const visitedPages = useVisitedPages(); - const { summary, streamSummary } = useSummaries( - useShallow((state) => { - return { - summary: state.getSummary({ targetSpaceId, targetPageId }), - streamSummary: state.streamSummary, - }; - }) - ); - - useEffect(() => { - streamSummary({ - currentSpaceId: currentPage.spaceId, - currentPageId: currentPage.pageId, - currentPageTitle: currentPage.title, - targetSpaceId, - targetPageId, - linkPreview, - linkTitle, - visitedPages, - }); - }, [ - currentPage.pageId, - currentPage.spaceId, - currentPage.title, - targetSpaceId, - targetPageId, - linkPreview, - linkTitle, - visitedPages, - streamSummary, - ]); - - const shimmerBlocks = [ - 'w-[20%] [animation-delay:-1s]', - 'w-[35%] [animation-delay:-0.8s]', - 'w-[25%] [animation-delay:-0.6s]', - 'w-[10%] [animation-delay:-0.4s]', - 'w-[40%] [animation-delay:-0.2s]', - 'w-[30%] [animation-delay:0s]', - ]; - - return ( -
-
- {showTrademark ? ( - - ) : ( - - )} -
{t(language, 'link_tooltip_ai_summary')}
-
- {summary.length > 0 ? ( -

{summary}

- ) : ( -
- {shimmerBlocks.map((block, index) => ( -
- ))} -
- )} - {summary.length > 0 ? ( -
- {t(language, 'link_tooltip_ai_summary_description')} -
- ) : null} -
- ); -} diff --git a/packages/gitbook/src/components/AIPageLinkSummary/index.ts b/packages/gitbook/src/components/AIPageLinkSummary/index.ts deleted file mode 100644 index 2d93029d7..000000000 --- a/packages/gitbook/src/components/AIPageLinkSummary/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './AIPageLinkSummary'; diff --git a/packages/gitbook/src/components/AIPageLinkSummary/server-actions/index.ts b/packages/gitbook/src/components/AIPageLinkSummary/server-actions/index.ts deleted file mode 100644 index 664e869e2..000000000 --- a/packages/gitbook/src/components/AIPageLinkSummary/server-actions/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './streamLinkPageSummary'; diff --git a/packages/gitbook/src/components/AIPageLinkSummary/server-actions/streamLinkPageSummary.ts b/packages/gitbook/src/components/AIPageLinkSummary/server-actions/streamLinkPageSummary.ts deleted file mode 100644 index c696c4dc2..000000000 --- a/packages/gitbook/src/components/AIPageLinkSummary/server-actions/streamLinkPageSummary.ts +++ /dev/null @@ -1,157 +0,0 @@ -'use server'; -import { getSiteURLDataFromMiddleware } from '@/lib/middleware'; -import { getServerActionBaseContext } from '@/lib/server-actions'; -import { filterOutNullable } from '@/lib/typescript'; -import { AIMessageRole, AIModel } from '@gitbook/api'; -import { z } from 'zod'; -import { streamGenerateAIObject } from '../../AI/server-actions/api'; - -/** - * Get a summary of a page, in the context of another page - */ -export async function* streamLinkPageSummary({ - currentSpaceId, - currentPageId, - targetSpaceId, - targetPageId, - linkPreview, - linkTitle, - visitedPages, -}: { - currentSpaceId: string; - currentPageId: string; - currentPageTitle: string; - targetSpaceId: string; - targetPageId: string; - linkPreview?: string; - linkTitle?: string; - visitedPages?: Array<{ spaceId: string; pageId: string }>; -}) { - const baseContext = await getServerActionBaseContext(); - const siteURLData = await getSiteURLDataFromMiddleware(); - - const { stream } = await streamGenerateAIObject(baseContext, { - organizationId: siteURLData.organization, - siteId: siteURLData.site, - model: AIModel.Fast, - schema: z.object({ - highlight: z.string().describe('The reason why the user should read the target page.'), - }), - input: [ - { - role: AIMessageRole.Developer, - content: `# 1. Role -You are a contextual fact extractor. Your job is to find the exact fact from the linked page that directly answers the implied question in the current paragraph. - -# 2. Task -Extract a contextually-relevant fact that: -- Directly answers the specific need or question implied by the link's placement -- States a capability, limitation, or specification from the target page -- Connects precisely to the user's current paragraph or sentence -- Completes the user's understanding based on what they're currently reading - -# 3. Instructions -1. First, identify the exact need, question, or gap in the current paragraph where the link appears -2. Find the specific fact in the target page that addresses this exact contextual need -3. Ensure the fact relates directly to the context of the paragraph containing the link -4. Avoid ALL instructional language including words like "use", "click", "select", "create" -5. Keep it under 30 words, factual and declarative about what EXISTS or IS TRUE`, - }, - { - role: AIMessageRole.Developer, - content: `# 4. Current page -The content of the current page is:`, - attachments: [ - { - type: 'page' as const, - spaceId: currentSpaceId, - pageId: currentPageId, - }, - ], - }, - ...(visitedPages - ? [ - { - role: AIMessageRole.Developer, - content: '# 5. Previous pages', - }, - ...visitedPages.map(({ spaceId, pageId }) => ({ - role: AIMessageRole.Developer, - content: `## Page ${pageId}`, - attachments: [ - { - type: 'page' as const, - spaceId, - pageId, - }, - ], - })), - ] - : []), - { - role: AIMessageRole.Developer, - content: `# 6. Target page -The content of the target page is:`, - attachments: [ - { - type: 'page' as const, - spaceId: targetSpaceId, - pageId: targetPageId, - }, - ], - }, - { - role: AIMessageRole.Developer, - content: `# 7. Link preview -The content of the link preview is: -> ${linkPreview} -> Page ID: ${targetPageId}`, - }, - { - role: AIMessageRole.Developer, - content: `# 8. Guidelines & Examples -ALWAYS: -- ALWAYS choose facts that directly fulfill the contextual need where the link appears -- ALWAYS connect target page information specifically to the current paragraph context -- ALWAYS focus on the gap in knowledge that the link is meant to fill -- ALWAYS consider user's navigation history to ensure contextual continuity -- ALWAYS use action verbs like "click", "select", "use", "create", "enable" - -NEVER: -- NEVER include ANY unspecifc language like "learn", "how to", "discover", etc. State the fact directly. -- NEVER select general facts unrelated to the specific link context -- NEVER ignore the specific context where the link appears -- NEVER repeat the same fact in different words - -## Examples -Current paragraph: "When organizing content, headings are limited to 3 levels. For more advanced editing, you can use (multiple select)[/multiple-select] to move multiple blocks at once." -Preview: "Multiple Select: Select multiple content blocks at once." -✓ "Shift selects content between two points, useful for reorganizing your current heading structure." -✗ "Shift and Ctrl/Cmd keys are the modifiers for selecting multiple blocks." - -Current paragraph: "Most changes can be published directly, but for major revisions, if you want others to review changes before publishing, create a (change request)[/change-requests]." -Preview: "Change Requests: Collaborative content editing workflow." -✓ "Each reviewer's approval is tracked separately, with specific change highlighting for your major revisions." -✗ "Each reviewer receives an email notification and can approve or request changes." - -Current paragraph: "Your team mentioned issues with conflicting edits. Need to collaborate in real-time? You can use (live edit mode)[/live-edit]." -Preview: "Live Edit: Real-time collaborative editing." -✓ "Teams with GitHub repositories (like yours) cannot use this feature due to sync limitations." -✗ "Incompatible with GitHub/GitLab sync and requires specific visibility settings."`, - }, - { - role: AIMessageRole.User, - content: `I'm considering reading the link titled "${linkTitle}" pointing to page ${targetPageId}. Why should I read it? Relate it to the paragraph I'm currently reading.`, - }, - ].filter(filterOutNullable), - }); - - for await (const value of stream) { - const highlight = value.highlight; - if (!highlight) { - continue; - } - - yield highlight; - } -} diff --git a/packages/gitbook/src/components/DocumentView/InlineLink/InlineLink.tsx b/packages/gitbook/src/components/DocumentView/InlineLink/InlineLink.tsx index 3759894a1..7a9645883 100644 --- a/packages/gitbook/src/components/DocumentView/InlineLink/InlineLink.tsx +++ b/packages/gitbook/src/components/DocumentView/InlineLink/InlineLink.tsx @@ -108,37 +108,11 @@ function InlineLinkTooltipWrapper(props: { resolved.subText = undefined; } - const aiSummary: { pageId: string; spaceId: string } | undefined = (() => { - if (isExternal) { - return; - } - - if (isSamePage) { - return; - } - - if (!('customization' in context) || !context.customization.ai?.pageLinkSummaries.enabled) { - return; - } - - if (!('page' in context) || !('page' in inline.data.ref)) { - return; - } - - if (inline.data.ref.kind === 'page' || inline.data.ref.kind === 'anchor') { - return { - pageId: resolved.page?.id ?? inline.data.ref.page ?? context.page.id, - spaceId: inline.data.ref.space ?? context.space.id, - }; - } - })(); - return ( ; target: { href: string; diff --git a/packages/gitbook/src/components/DocumentView/InlineLink/InlineLinkTooltipImpl.tsx b/packages/gitbook/src/components/DocumentView/InlineLink/InlineLinkTooltipImpl.tsx index ac32924aa..22547cefc 100644 --- a/packages/gitbook/src/components/DocumentView/InlineLink/InlineLinkTooltipImpl.tsx +++ b/packages/gitbook/src/components/DocumentView/InlineLink/InlineLinkTooltipImpl.tsx @@ -3,13 +3,11 @@ import { tcls } from '@/lib/tailwind'; import { Icon } from '@gitbook/icons'; import * as Tooltip from '@radix-ui/react-tooltip'; import { Fragment } from 'react'; -import { AIPageLinkSummary } from '../../AIPageLinkSummary'; import { Button, StyledLink } from '../../primitives'; export function InlineLinkTooltipImpl(props: { isSamePage: boolean; isExternal: boolean; - aiSummary?: { pageId: string; spaceId: string }; breadcrumbs: Array<{ href?: string; label: string; icon?: React.ReactNode }>; target: { href: string; @@ -20,8 +18,7 @@ export function InlineLinkTooltipImpl(props: { openInNewTabLabel: string; children: React.ReactNode; }) { - const { isSamePage, isExternal, aiSummary, openInNewTabLabel, target, breadcrumbs, children } = - props; + const { isSamePage, isExternal, openInNewTabLabel, target, breadcrumbs, children } = props; return ( @@ -102,22 +99,8 @@ export function InlineLinkTooltipImpl(props: {

{target.subText}

) : null}
- - {aiSummary ? ( -
- -
- ) : null} - + diff --git a/packages/gitbook/src/intl/translations/de.ts b/packages/gitbook/src/intl/translations/de.ts index 49f1eecf4..65242a87c 100644 --- a/packages/gitbook/src/intl/translations/de.ts +++ b/packages/gitbook/src/intl/translations/de.ts @@ -63,8 +63,6 @@ export const de = { more: 'Mehr', link_tooltip_external_link: 'Externe Verlinkung zu', link_tooltip_page_anchor: 'Zum Abschnitt springen', - link_tooltip_ai_summary: 'Seitenhighlight', - link_tooltip_ai_summary_description: 'Basierend auf Ihrem Kontext. Kann Fehler enthalten.', open_in_new_tab: 'In neuem Tab öffnen', ai_chat_assistant_name: 'Docs-Assistent', ai_chat_assistant_description: 'Ich helfe Ihnen bei der Dokumentation.', diff --git a/packages/gitbook/src/intl/translations/en.ts b/packages/gitbook/src/intl/translations/en.ts index 5ac034020..b8d930229 100644 --- a/packages/gitbook/src/intl/translations/en.ts +++ b/packages/gitbook/src/intl/translations/en.ts @@ -61,8 +61,6 @@ export const en = { more: 'More', link_tooltip_external_link: 'External link to', link_tooltip_page_anchor: 'Jump to section', - link_tooltip_ai_summary: 'Page highlight', - link_tooltip_ai_summary_description: 'Based on your context. May contain mistakes.', open_in_new_tab: 'Open in new tab', ai_chat_assistant_name: 'Docs Assistant', ai_chat_assistant_description: "I'm here to help you with the docs.", diff --git a/packages/gitbook/src/intl/translations/es.ts b/packages/gitbook/src/intl/translations/es.ts index 81a0d670b..fcd857fa6 100644 --- a/packages/gitbook/src/intl/translations/es.ts +++ b/packages/gitbook/src/intl/translations/es.ts @@ -65,8 +65,6 @@ export const es: TranslationLanguage = { more: 'Más', link_tooltip_external_link: 'Enlace externo a', link_tooltip_page_anchor: 'Saltar a la sección', - link_tooltip_ai_summary: 'Resumen de la página', - link_tooltip_ai_summary_description: 'Basado en tu contexto. Puede contener errores.', open_in_new_tab: 'Abrir en una nueva pestaña', ai_chat_assistant_name: 'Asistente de Docs', ai_chat_assistant_description: 'Estoy aquí para ayudarte con la documentación.', diff --git a/packages/gitbook/src/intl/translations/fr.ts b/packages/gitbook/src/intl/translations/fr.ts index 7d49171cc..b2c945cc1 100644 --- a/packages/gitbook/src/intl/translations/fr.ts +++ b/packages/gitbook/src/intl/translations/fr.ts @@ -63,8 +63,6 @@ export const fr: TranslationLanguage = { more: 'Plus', link_tooltip_external_link: 'Lien externe à', link_tooltip_page_anchor: 'Sauter à la section', - link_tooltip_ai_summary: 'Résumé de la page', - link_tooltip_ai_summary_description: 'Basé sur votre contexte. Peut contenir des erreurs.', open_in_new_tab: 'Ouvrir dans un nouvel onglet', ai_chat_assistant_name: 'Assistant Docs', ai_chat_assistant_description: 'Je suis là pour vous aider avec la documentation.', diff --git a/packages/gitbook/src/intl/translations/ja.ts b/packages/gitbook/src/intl/translations/ja.ts index 223dc8d70..70f9c3774 100644 --- a/packages/gitbook/src/intl/translations/ja.ts +++ b/packages/gitbook/src/intl/translations/ja.ts @@ -63,9 +63,6 @@ export const ja: TranslationLanguage = { more: '詳細', link_tooltip_external_link: '外部リンク先', link_tooltip_page_anchor: 'ページ内リンク先', - link_tooltip_ai_summary: 'ページのハイライト', - link_tooltip_ai_summary_description: - 'あなたのコンテキストに基づいています。間違いが含まれる可能性があります。', open_in_new_tab: '新しいタブで開く', ai_chat_assistant_name: 'ドキュメントアシスタント', ai_chat_assistant_description: 'ドキュメントについてお手伝いします。', diff --git a/packages/gitbook/src/intl/translations/nl.ts b/packages/gitbook/src/intl/translations/nl.ts index 8f824a72f..da1580e31 100644 --- a/packages/gitbook/src/intl/translations/nl.ts +++ b/packages/gitbook/src/intl/translations/nl.ts @@ -63,8 +63,6 @@ export const nl: TranslationLanguage = { more: 'Meer', link_tooltip_external_link: 'Externe link naar', link_tooltip_page_anchor: 'Spring naar sectie', - link_tooltip_ai_summary: 'Pagina-samenvatting', - link_tooltip_ai_summary_description: 'Gebaseerd op je context. Kan fouten bevatten.', open_in_new_tab: 'Open in nieuw tabblad', ai_chat_assistant_name: 'Docs Assistent', ai_chat_assistant_description: 'Ik help je met de documentatie.', diff --git a/packages/gitbook/src/intl/translations/no.ts b/packages/gitbook/src/intl/translations/no.ts index e1c962b00..c4ec86b61 100644 --- a/packages/gitbook/src/intl/translations/no.ts +++ b/packages/gitbook/src/intl/translations/no.ts @@ -63,8 +63,6 @@ export const no: TranslationLanguage = { more: 'Mer', link_tooltip_external_link: 'Ekstern lenke til', link_tooltip_page_anchor: 'Hopp til seksjon', - link_tooltip_ai_summary: 'Sidesammendrag', - link_tooltip_ai_summary_description: 'Basert på din kontekst. Kan inneholde feil.', open_in_new_tab: 'Åpne i ny fane', ai_chat_assistant_name: 'Docs-assistent', ai_chat_assistant_description: 'Jeg er her for å hjelpe deg med docs.', diff --git a/packages/gitbook/src/intl/translations/pt-br.ts b/packages/gitbook/src/intl/translations/pt-br.ts index cc594d582..a4743dc8f 100644 --- a/packages/gitbook/src/intl/translations/pt-br.ts +++ b/packages/gitbook/src/intl/translations/pt-br.ts @@ -63,8 +63,6 @@ export const pt_br = { more: 'Mais', link_tooltip_external_link: 'Link externo para', link_tooltip_page_anchor: 'Pular para a seção', - link_tooltip_ai_summary: 'Resumo da página', - link_tooltip_ai_summary_description: 'Baseado no seu contexto. Pode conter erros.', open_in_new_tab: 'Abrir em uma nova guia', ai_chat_assistant_name: 'Assistente de Docs', ai_chat_assistant_description: 'Estou aqui para ajudá-lo com a documentação.', diff --git a/packages/gitbook/src/intl/translations/zh.ts b/packages/gitbook/src/intl/translations/zh.ts index 4cb1c07ed..c51ce850f 100644 --- a/packages/gitbook/src/intl/translations/zh.ts +++ b/packages/gitbook/src/intl/translations/zh.ts @@ -61,8 +61,6 @@ export const zh: TranslationLanguage = { more: '更多', link_tooltip_external_link: '外部链接到', link_tooltip_page_anchor: '跳转到页面', - link_tooltip_ai_summary: '页面要点', - link_tooltip_ai_summary_description: '基于您的上下文。可能包含错误。', open_in_new_tab: '在新标签页中打开', ai_chat_assistant_name: '文档助手', ai_chat_assistant_description: '我在这里帮助您了解文档。',