Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions docs/product/explore/logs/getting-started/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ To set up Sentry Logs, use the links below for supported SDKs. After it's been s
platform="javascript.browser"
label="Browser JavaScript"
url="/platforms/javascript/logs/"
skill="sentry-browser-sdk"
/>
- <LinkWithPlatformIcon
platform="javascript.angular"
Expand Down Expand Up @@ -44,6 +45,7 @@ To set up Sentry Logs, use the links below for supported SDKs. After it's been s
platform="javascript.cloudflare"
label="Cloudflare"
url="/platforms/javascript/guides/cloudflare/logs/"
skill="sentry-cloudflare-sdk"
/>
- <LinkWithPlatformIcon
platform="javascript.connect"
Expand Down Expand Up @@ -99,16 +101,19 @@ To set up Sentry Logs, use the links below for supported SDKs. After it's been s
platform="javascript.nestjs"
label="Nest.js"
url="/platforms/javascript/guides/nestjs/logs/"
skill="sentry-nestjs-sdk"
/>
- <LinkWithPlatformIcon
platform="javascript.node"
label="Node.js"
url="/platforms/javascript/guides/node/logs/"
skill="sentry-node-sdk"
/>
- <LinkWithPlatformIcon
platform="javascript.nextjs"
label="Next.js"
url="/platforms/javascript/guides/nextjs/logs/"
skill="sentry-nextjs-sdk"
/>
- <LinkWithPlatformIcon
platform="javascript.nuxt"
Expand All @@ -119,11 +124,13 @@ To set up Sentry Logs, use the links below for supported SDKs. After it's been s
platform="javascript.react"
label="React"
url="/platforms/javascript/guides/react/logs/"
skill="sentry-react-sdk"
/>
- <LinkWithPlatformIcon
platform="javascript.react-router"
label="React Router"
url="/platforms/javascript/guides/react-router/logs/"
skill="sentry-react-router-framework-sdk"
/>
- <LinkWithPlatformIcon
platform="javascript.remix"
Expand All @@ -144,16 +151,19 @@ To set up Sentry Logs, use the links below for supported SDKs. After it's been s
platform="javascript.svelte"
label="Svelte"
url="/platforms/javascript/guides/svelte/logs/"
skill="sentry-svelte-sdk"
/>
- <LinkWithPlatformIcon
platform="javascript.sveltekit"
label="SvelteKit"
url="/platforms/javascript/guides/sveltekit/logs/"
skill="sentry-svelte-sdk"
/>
- <LinkWithPlatformIcon
platform="javascript.tanstackstart-react"
label="TanStack Start"
url="/platforms/javascript/guides/tanstackstart-react/logs/"
skill="sentry-tanstack-start-sdk"
/>
- <LinkWithPlatformIcon
platform="javascript.vue"
Expand Down Expand Up @@ -190,11 +200,13 @@ To set up Sentry Logs, use the links below for supported SDKs. After it's been s
platform="android"
label="Android"
url="/platforms/android/logs/"
skill="sentry-android-sdk"
/>
- <LinkWithPlatformIcon
platform="apple"
label="Apple"
url="/platforms/apple/logs/"
skill="sentry-cocoa-sdk"
/>
- <LinkWithPlatformIcon
platform="capacitor"
Expand All @@ -205,16 +217,18 @@ To set up Sentry Logs, use the links below for supported SDKs. After it's been s
platform="dart.flutter"
label="Flutter"
url="/platforms/dart/guides/flutter/logs/"
skill="sentry-flutter-sdk"
/>
- <LinkWithPlatformIcon
platform="react-native"
label="React Native"
url="/platforms/react-native/logs/"
skill="sentry-react-native-sdk"
/>

### PHP

- <LinkWithPlatformIcon platform="php" label="PHP" url="/platforms/php/logs/" />
- <LinkWithPlatformIcon platform="php" label="PHP" url="/platforms/php/logs/" skill="sentry-php-sdk" />
- <LinkWithPlatformIcon
platform="php.symfony"
label="Symfony"
Expand All @@ -232,6 +246,7 @@ To set up Sentry Logs, use the links below for supported SDKs. After it's been s
platform="python"
label="Python"
url="/platforms/python/logs/"
skill="sentry-python-sdk"
/>

### Ruby
Expand All @@ -240,6 +255,7 @@ To set up Sentry Logs, use the links below for supported SDKs. After it's been s
platform="ruby"
label="Ruby"
url="/platforms/ruby/logs/"
skill="sentry-ruby-sdk"
/>
- <LinkWithPlatformIcon
platform="ruby.rails"
Expand All @@ -249,7 +265,7 @@ To set up Sentry Logs, use the links below for supported SDKs. After it's been s

### Go

- <LinkWithPlatformIcon platform="go" label="Go" url="/platforms/go/logs/" />
- <LinkWithPlatformIcon platform="go" label="Go" url="/platforms/go/logs/" skill="sentry-go-sdk" />

### Rust

Expand All @@ -265,6 +281,7 @@ To set up Sentry Logs, use the links below for supported SDKs. After it's been s
platform="dotnet"
label=".NET"
url="/platforms/dotnet/logs/"
skill="sentry-dotnet-sdk"
/>
- <LinkWithPlatformIcon
platform="dotnet.aspnetcore"
Expand Down
30 changes: 1 addition & 29 deletions src/components/agentSkillsCallout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,44 +9,16 @@ import {DocMetrics} from 'sentry-docs/metrics';

import {CodeBlock} from '../codeBlock';
import {CodeTabs} from '../codeTabs';
import {buildDotagentsCommand, buildNpxSkillsCommand, buildPrompt} from './shared';
import styles from './style.module.scss';

const SKILLS_BASE_URL = 'https://skills.sentry.dev';
const SKILLS_REPO = 'getsentry/sentry-for-ai';

type Props = {
/** Display name for the platform, e.g. "Next.js", "Python". Omit for generic. */
platformName?: string;
/** Skill package name, e.g. "sentry-nextjs-sdk". Omit for generic/all skills. */
skill?: string;
};

function buildPromptUrl(skill?: string): string {
if (!skill) {
return SKILLS_BASE_URL + '/';
}
return `${SKILLS_BASE_URL}/${skill}/SKILL.md`;
}

function buildPrompt(skill?: string): string {
const url = buildPromptUrl(skill);
return `Use curl to download, read and follow: ${url}`;
}

function buildDotagentsCommand(skill?: string): string {
if (!skill) {
return `npx @sentry/dotagents add ${SKILLS_REPO} --all`;
}
return `npx @sentry/dotagents add ${SKILLS_REPO} --name ${skill}`;
}

function buildNpxSkillsCommand(skill?: string): string {
if (!skill) {
return `npx skills add ${SKILLS_REPO}`;
}
return `npx skills add ${SKILLS_REPO} --skill ${skill}`;
}

export function AgentSkillsCallout({skill, platformName}: Props) {
const [copied, setCopied] = useState(false);
const [isExpanded, setIsExpanded] = useState(false);
Expand Down
33 changes: 33 additions & 0 deletions src/components/agentSkillsCallout/shared.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Shared constants and utilities for agent skills prompt building.
* Used by AgentSkillsCallout (full banner) and inline copy-prompt buttons.
*/

export const SKILLS_BASE_URL = 'https://skills.sentry.dev';
export const SKILLS_REPO = 'getsentry/sentry-for-ai';

export function buildPromptUrl(skill?: string): string {
if (!skill) {
return SKILLS_BASE_URL + '/';
}
return `${SKILLS_BASE_URL}/${skill}/SKILL.md`;
}

export function buildPrompt(skill?: string): string {
const url = buildPromptUrl(skill);
return `Use curl to download, read and follow: ${url}`;
}

export function buildDotagentsCommand(skill?: string): string {
if (!skill) {
return `npx @sentry/dotagents add ${SKILLS_REPO} --all`;
}
return `npx @sentry/dotagents add ${SKILLS_REPO} --name ${skill}`;
}

export function buildNpxSkillsCommand(skill?: string): string {
if (!skill) {
return `npx skills add ${SKILLS_REPO}`;
}
return `npx skills add ${SKILLS_REPO} --skill ${skill}`;
}
132 changes: 132 additions & 0 deletions src/components/copyPromptButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
'use client';

import * as Tooltip from '@radix-ui/react-tooltip';
import {Theme} from '@radix-ui/themes';
import * as Sentry from '@sentry/nextjs';
import {useTheme} from 'next-themes';
import {useCallback, useMemo, useState} from 'react';
import {usePlausibleEvent} from 'sentry-docs/hooks/usePlausibleEvent';
import {DocMetrics} from 'sentry-docs/metrics';

import {buildPrompt} from '../agentSkillsCallout/shared';
import styles from './style.module.scss';

type Props = {
/** Skill package name, e.g. "sentry-nextjs-sdk". */
skill: string;
};

export function CopyPromptButton({skill}: Props) {
const [copied, setCopied] = useState(false);
const {emit} = usePlausibleEvent();
const {resolvedTheme} = useTheme();
const isDark = resolvedTheme === 'dark';

const prompt = buildPrompt(skill);

/**
* Tooltip styles matching the onboarding tooltip pattern.
* Inline styles are required because Radix portals the tooltip to document.body,
* outside the Theme wrapper, so CSS module classes don't reliably apply.
*/
const tooltipContentStyle: React.CSSProperties = useMemo(
() => ({
borderRadius: '4px',
padding: '8px 12px',
fontSize: '12px',
lineHeight: 1.2,
textAlign: 'center' as const,
color: isDark ? 'var(--foreground)' : 'var(--gray-11)',
backgroundColor: isDark ? 'var(--gray-4)' : 'white',
boxShadow: '0px 4px 16px 0px rgba(31, 22, 51, 0.1)',
zIndex: 9999,
position: 'relative' as const,
pointerEvents: 'none' as const,
userSelect: 'none' as const,
whiteSpace: 'nowrap' as const,
animationDuration: '100ms',
animationTimingFunction: 'ease-in',
}),
[isDark]
);

const tooltipArrowStyle: React.CSSProperties = useMemo(
() => ({
fill: isDark ? 'var(--gray-4)' : 'white',
}),
[isDark]
);

const copyPrompt = useCallback(
async (event: React.MouseEvent<HTMLButtonElement>) => {
event.stopPropagation();
event.preventDefault();

emit('Copy AI Prompt', {
props: {page: window.location.pathname, title: 'Inline Platform Link'},
});

try {
setCopied(false);
await navigator.clipboard.writeText(prompt);
setCopied(true);
DocMetrics.copyAIPrompt(window.location.pathname, skill, true);
setTimeout(() => setCopied(false), 1500);
} catch (error) {
Sentry.captureException(error);
DocMetrics.copyAIPrompt(window.location.pathname, skill, false);
setCopied(false);
}
},
[prompt, emit, skill]
);

return (
<span className={styles.wrapper}>
<span className={styles.divider}>|</span>
<Tooltip.Provider delayDuration={200}>
<Tooltip.Root>
<Tooltip.Trigger asChild>
<button
className={styles.button}
onClick={copyPrompt}
type="button"
aria-label="Copy setup prompt for AI agents"
>
<CopyIcon />
<span className={styles.label}>{copied ? 'Copied!' : 'Copy Prompt'}</span>
</button>
</Tooltip.Trigger>
{!copied && (
<Tooltip.Portal>
<Theme accentColor="iris">
<Tooltip.Content style={tooltipContentStyle} sideOffset={6}>
Copy setup prompt for AI agents
<Tooltip.Arrow style={tooltipArrowStyle} />
</Tooltip.Content>
</Theme>
</Tooltip.Portal>
)}
</Tooltip.Root>
</Tooltip.Provider>
</span>
);
}

function CopyIcon() {
return (
<svg
width="12"
height="12"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
</svg>
);
}
Loading
Loading