feat: Replace Kapa AI with first-party docs-mcp chat#17632
Draft
MathurAditya724 wants to merge 14 commits intomasterfrom
Draft
feat: Replace Kapa AI with first-party docs-mcp chat#17632MathurAditya724 wants to merge 14 commits intomasterfrom
MathurAditya724 wants to merge 14 commits intomasterfrom
Conversation
Remove the third-party Kapa AI widget and replace it with a custom AI chat modal powered by the docs-mcp Cloudflare Worker. Changes: - Add AskAiProvider context for modal open/close state management - Add AskAiModal chat component with streaming, multi-turn support, markdown rendering, and example questions - Rewire all Ask AI trigger points (search bar, header, inline search result, ?askAI=true deep link) to use the new context - Remove Kapa widget script, CSS, TypeScript types, and CSP entries - Add docs-mcp.getsentry.workers.dev to CSP connect-src - Add NEXT_PUBLIC_ASK_AI_API_URL env var Co-Authored-By: Claude <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…erer Address CodeQL security finding (DOM text reinterpreted as HTML) by replacing the string-based renderMarkdown + dangerouslySetInnerHTML approach with a React-element-based markdown parser that produces safe ReactNode trees directly. Also fix broken link in AGENTS.md (remove protocol from docs-mcp URL to prevent lychee from checking a worker with no root route). Co-Authored-By: Claude <noreply@anthropic.com>
Overhaul the chat modal design inspired by AI SDK elements: - Full-width assistant messages with avatar icon + action bar (copy, retry) instead of bubble layout - Animated streaming cursor (blinking caret) replaces bounce dots - Polished input area with bordered container + arrow submit button - Gradient-branded empty state with clickable suggestion cards - Slide-up entrance animation - Mobile-friendly: full-height on small screens, centered on desktop - Loading spinner on submit button during streaming - Better prose typography with refined spacing for code blocks, headings, lists, and links Co-Authored-By: Claude <noreply@anthropic.com>
The modal was rendering as a sibling of <Theme>, so it didn't inherit any Radix theme CSS variables (--gray-*, --accent-*, --foreground, etc.) or typography styles. Move it inside <Theme> so all the design tokens apply correctly. Co-Authored-By: Claude <noreply@anthropic.com>
CodeQL flagged the renderInline() function for passing unsanitized AI response text directly into anchor href attributes. Add an allow-list check so only http:// and https:// URLs are used; anything else renders as '#' to prevent javascript: URL injection. Co-Authored-By: Claude <noreply@anthropic.com>
The docs-mcp.getsentry.workers.dev Cloudflare Worker only serves /mcp and /api/ask routes — the root URL returns 404. Add it to .lycheeignore so lychee link checker doesn't fail on URLs in plan files and AGENTS.md that reference the worker hostname. Co-Authored-By: Claude <noreply@anthropic.com>
CodeQL's taint analysis tracks data flow from untrusted AI response text through the ternary operator into the href attribute, flagging it as XSS even with an allow-list check. Parse the URL through the URL constructor and read back parsed.href to break the taint chain — the output value is constructed from safe URL object fields rather than copied from user-controlled input. Co-Authored-By: Claude <noreply@anthropic.com>
Move AskAiModal inside <Theme> so it inherits all Radix CSS variables (--gray-*, --accent-*, --foreground, etc.). Previously it was a sibling of Theme, causing all design tokens to be missing. Also remove 'Powered by Sentry docs' text from the input area. Co-Authored-By: Claude <noreply@anthropic.com>
Switch backend→frontend communication from raw text to structured SSE with typed events (text, tool_start, tool_end, error, done) so the frontend can show tool-execution status and distinguish errors from content. Rewrite the Ask AI modal with: - SSE event parsing and AbortController cancel support - Runtime syntax highlighting via refractor + prism-sentry theme - Per-code-block copy buttons with language labels - Proper relative-URL handling for doc links (/platforms/... → docs.sentry.io) - Table, blockquote, and strikethrough markdown support - Scoped ask-ai-prose CSS replacing inline Tailwind arbitrary variants - Stop button to cancel in-flight requests Move prism-sentry/index.css import to root layout so token colors are available in the modal (rendered outside [[...path]] layout). Co-Authored-By: Claude <noreply@anthropic.com>
Modal background (--gray-1) was identical to the page background in dark mode (both #111110 in sand theme), making the modal appear transparent. Bump to --gray-2 for modal bg, --gray-3 for input bg, and raise all alpha borders from a3→a5 so elements are visible. Also bump hover backgrounds from a3→a4 and inline code bg from a3→a4 to ensure interactive states are perceptible in dark mode. Increase backdrop opacity from 50% to 60% for better page dimming. Co-Authored-By: Claude <noreply@anthropic.com>
The alpha-based gray scale (--gray-a3 through --gray-a5) produces nearly invisible borders and backgrounds on near-black dark mode surfaces because the alpha values are only 7-20% opacity white. Switch all structural borders and backgrounds to the solid gray scale (--gray-4 through --gray-6) which has proper dark mode values like #2a2a28, #31312e, #3b3a37 — visibly distinct from the #111110 page background. Co-Authored-By: Claude <noreply@anthropic.com>
Tighten the empty state layout: smaller icon, less vertical padding, narrower max-width. Add a 'Try asking' section label above the example buttons. Buttons now have a visible bg fill (--gray-3) with solid border (--gray-5) and hover to accent-purple border. Reduce font sizes and gaps for a more compact, polished look. Co-Authored-By: Claude <noreply@anthropic.com>
Replace hand-rolled buttons with Radix Button/IconButton matching the site's established patterns (variant='ghost' color='gray' for toolbar actions, variant='solid' for primary submit). Use Radix ScrollArea and Separator for consistent behavior. Fix dark mode visibility by using the solid Radix gray scale (--gray-4/5/6) instead of the alpha scale (--gray-a3/a4/a5) which produces near-invisible colors on dark backgrounds. Integrate prism-sentry syntax highlighting via refractor for code blocks, with a header bar matching the site's CodeBlock component. Add proper prose styles via scoped CSS. Support relative doc URLs (/platforms/... -> docs.sentry.io). Use Radix accent tokens (--accent-9, --accent-11) for consistent theming. Co-Authored-By: Claude <noreply@anthropic.com>
Replace hand-rolled buttons with Radix Button/IconButton matching the site's established patterns (variant='ghost' color='gray' for toolbar actions, variant='solid' for primary submit). Use Radix ScrollArea and Separator for consistent behavior. Fix dark mode visibility by using the solid Radix gray scale (--gray-4/5/6) instead of the alpha scale (--gray-a3/a4/a5) which produces near-invisible colors on dark backgrounds. Override the ScrollArea's width: fit-content rule that was collapsing content. Move all prose/heading/table/blockquote styles to a scoped .ask-ai-prose CSS class. Integrate prism-sentry syntax highlighting via refractor for code blocks, with a header bar matching the site's CodeBlock component. Support relative doc URLs (/platforms/... -> docs.sentry.io). Use Radix accent tokens (--accent-9, --accent-11) for consistent theming across light and dark modes. Co-Authored-By: Claude <noreply@anthropic.com>
| const lm = token.match(/^\[([^\]]+)\]\(([^)]+)\)$/); | ||
| if (lm) { | ||
| out.push( | ||
| <a key={k} href={sanitizeHref(lm[2])} target="_blank" rel="noopener noreferrer"> |
Member
Author
There was a problem hiding this comment.
False positive — React sets href as a DOM property via setAttribute, not through innerHTML. There's no HTML reinterpretation happening here. The link text (lm[1]) is also safe since React auto-escapes text children in JSX.
sanitizeHref already validates the protocol (only https:/http: or relative paths prefixed with https://docs.sentry.io), so javascript: URIs are blocked too.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
DESCRIBE YOUR PR
Replace the third-party Kapa AI widget with a first-party AI chat modal powered by the
docs-mcpCloudflare Worker (getsentry/cli-init-api).What changed:
AskAiModalchat component with streaming responses, multi-turn conversation, markdown rendering, and example questionsAskAiProviderReact context to manage modal state?askAI=trueURL deep link) to use the new modalwidget.kapa.aiandkapa-widget-proxy, addeddocs-mcp.getsentry.workers.devWhy:
.mdexports for retrieval (always up-to-date)Companion PR: https://github.com/getsentry/cli-init-api/pull/124 (adds
POST /api/askendpoint to docs-mcp)IS YOUR CHANGE URGENT?
PRE-MERGE CHECKLIST