feat: improve example-usage

pull/715/head
Travis Fischer 2025-06-24 20:41:55 -05:00
rodzic 7b5f7e8f97
commit 591a5d65c3
5 zmienionych plików z 149 dodań i 61 usunięć

Wyświetl plik

@ -7,6 +7,7 @@ import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import { AgenticProvider } from '@/components/agentic-provider' import { AgenticProvider } from '@/components/agentic-provider'
import { PostHogProvider } from '@/components/posthog-provider' import { PostHogProvider } from '@/components/posthog-provider'
import { ThemeProvider } from '@/components/theme-provider' import { ThemeProvider } from '@/components/theme-provider'
import { TooltipProvider } from '@/components/ui/tooltip'
import { queryClient } from '@/lib/query-client' import { queryClient } from '@/lib/query-client'
export default function Providers({ children }: { children: React.ReactNode }) { export default function Providers({ children }: { children: React.ReactNode }) {
@ -19,7 +20,7 @@ export default function Providers({ children }: { children: React.ReactNode }) {
disableTransitionOnChange disableTransitionOnChange
> >
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
{children} <TooltipProvider>{children}</TooltipProvider>
<ReactQueryDevtools /> <ReactQueryDevtools />
</QueryClientProvider> </QueryClientProvider>

Wyświetl plik

@ -11,6 +11,11 @@ import {
import { jsx, jsxs } from 'react/jsx-runtime' import { jsx, jsxs } from 'react/jsx-runtime'
import { type BundledLanguage, codeToHast } from 'shiki/bundle/web' import { type BundledLanguage, codeToHast } from 'shiki/bundle/web'
import {
Tooltip,
TooltipContent,
TooltipTrigger
} from '@/components/ui/tooltip'
import { toastError } from '@/lib/notifications' import { toastError } from '@/lib/notifications'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
@ -71,7 +76,7 @@ export function CodeBlock({
code, code,
lang, lang,
theme, theme,
className: 'rounded-sm w-full text-wrap p-4 text-sm' className: 'w-full text-wrap p-4 text-sm'
}).then(setNodes) }).then(setNodes)
}, [code, lang, theme]) }, [code, lang, theme])
@ -102,19 +107,34 @@ export function CodeBlock({
})() })()
}, [code, timeoutRef]) }, [code, timeoutRef])
const numNewLines = code.split('\n').length
return ( return (
<div className={cn('relative group rounded-sm w-full', className)}> <div
className={cn('relative group rounded-sm w-full shadow-sm', className)}
>
{nodes ? ( {nodes ? (
<> <>
{nodes} {nodes}
<Button <Tooltip>
variant='outline' <TooltipTrigger asChild>
className='absolute top-4 right-4 px-2.5! opacity-0 group-hover:opacity-100 group-hover:duration-0 transition-opacity duration-150' <Button
onClick={onCopy} variant='outline'
> className={cn(
{isCopied ? <CheckIcon /> : <CopyIcon />} 'absolute right-4 px-2.5! opacity-0 group-hover:opacity-100 group-hover:duration-0 transition-opacity duration-150',
</Button> numNewLines <= 1 ? 'top-[50%] translate-y-[-50%]' : 'top-4'
)}
onClick={onCopy}
>
{isCopied ? <CheckIcon /> : <CopyIcon />}
</Button>
</TooltipTrigger>
<TooltipContent side='bottom'>
{isCopied ? <span>Copied</span> : <span>Copy to clipboard</span>}
</TooltipContent>
</Tooltip>
</> </>
) : ( ) : (
<LoadingIndicator /> <LoadingIndicator />

Wyświetl plik

@ -8,7 +8,6 @@ import { Button } from '@/components/ui/button'
import { import {
Tooltip, Tooltip,
TooltipContent, TooltipContent,
TooltipProvider,
TooltipTrigger TooltipTrigger
} from '@/components/ui/tooltip' } from '@/components/ui/tooltip'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
@ -17,27 +16,23 @@ export function DarkModeToggle({ className }: { className?: string }) {
const { setTheme, resolvedTheme } = useTheme() const { setTheme, resolvedTheme } = useTheme()
return ( return (
<TooltipProvider> <Tooltip>
<Tooltip> <TooltipTrigger asChild>
<TooltipTrigger asChild> <Button
<Button variant='outline'
variant='outline' size='icon'
size='icon' className={cn('cursor-pointer', className)}
className={cn('cursor-pointer', className)} onClick={() => setTheme(resolvedTheme === 'dark' ? 'light' : 'dark')}
onClick={() => >
setTheme(resolvedTheme === 'dark' ? 'light' : 'dark') <Sun className='h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0' />
} <Moon className='absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100' />
> <span className='sr-only'>Toggle theme</span>
<Sun className='h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0' /> </Button>
<Moon className='absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100' /> </TooltipTrigger>
<span className='sr-only'>Toggle theme</span>
</Button>
</TooltipTrigger>
<TooltipContent> <TooltipContent>
<span>Toggle dark mode</span> <span>Toggle dark mode</span>
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
</TooltipProvider>
) )
} }

Wyświetl plik

@ -41,6 +41,7 @@ export function ExampleUsage() {
// TODO: allow to take the project and/or consumer in as props // TODO: allow to take the project and/or consumer in as props
// TODO: need a way of fetching a project and target deployment; same as in `AgenticToolClient.fromIdentifier` (currently only supports latest) // TODO: need a way of fetching a project and target deployment; same as in `AgenticToolClient.fromIdentifier` (currently only supports latest)
const projectIdentifier = '@agentic/search' const projectIdentifier = '@agentic/search'
const prompt = 'What is the latest news about AI?'
// Load the public project // Load the public project
const { const {
@ -98,7 +99,8 @@ export function ExampleUsage() {
config, config,
project, project,
deployment, deployment,
identifier: projectIdentifier identifier: projectIdentifier,
prompt
}) })
return ( return (

Wyświetl plik

@ -27,6 +27,7 @@ export type HTTPTarget = (typeof httpTargets)[number]
export const mcpClientTargetLabels = { export const mcpClientTargetLabels = {
url: 'MCP Server URL', url: 'MCP Server URL',
'claude-desktop': 'Claude Desktop', 'claude-desktop': 'Claude Desktop',
chatgpt: 'ChatGPT',
raycast: 'Raycast', raycast: 'Raycast',
cursor: 'Cursor', cursor: 'Cursor',
windsurf: 'Windsurf', windsurf: 'Windsurf',
@ -82,22 +83,30 @@ export type CodeSnippet = {
// install?: string // TODO // install?: string // TODO
} }
export function getCodeForDeveloperConfig(opts: { export type GetCodeForDeveloperConfigOpts = {
config: DeveloperConfig config: DeveloperConfig
project: Project project: Project
deployment: Deployment deployment: Deployment
identifier: string identifier: string
prompt: string
tool?: string tool?: string
}): CodeSnippet { }
export function getCodeForDeveloperConfig(
opts: GetCodeForDeveloperConfigOpts
): CodeSnippet {
const { config } = opts const { config } = opts
switch (config.target) { switch (config.target) {
case 'mcp': case 'mcp':
return getCodeForMCPClientConfig(opts) return getCodeForMCPClientConfig(opts)
case 'typescript': case 'typescript':
return getCodeForTSFrameworkConfig(opts) return getCodeForTSFrameworkConfig(opts)
case 'python': case 'python':
return getCodeForPythonFrameworkConfig(opts) return getCodeForPythonFrameworkConfig(opts)
case 'http': case 'http':
return getCodeForHTTPConfig(opts) return getCodeForHTTPConfig(opts)
} }
@ -105,11 +114,10 @@ export function getCodeForDeveloperConfig(opts: {
export function getCodeForMCPClientConfig({ export function getCodeForMCPClientConfig({
identifier identifier
}: { }: GetCodeForDeveloperConfigOpts): CodeSnippet {
identifier: string const mcpUrl = `${gatewayBaseUrl}/${identifier}/mcp`
}): CodeSnippet {
return { return {
code: `${gatewayBaseUrl}/${identifier}/mcp`, code: mcpUrl,
lang: 'bash' lang: 'bash'
} }
} }
@ -117,12 +125,8 @@ export function getCodeForMCPClientConfig({
export function getCodeForTSFrameworkConfig({ export function getCodeForTSFrameworkConfig({
config, config,
identifier, identifier,
prompt = 'What is the latest news about AI?' prompt
}: { }: GetCodeForDeveloperConfigOpts): CodeSnippet {
config: DeveloperConfig
identifier: string
prompt?: string
}): CodeSnippet {
switch (config.tsFrameworkTarget) { switch (config.tsFrameworkTarget) {
case 'ai': case 'ai':
return { return {
@ -341,16 +345,87 @@ console.log(JSON.stringify(result, null, 2))`.trim(),
} }
} }
export function getCodeForPythonFrameworkConfig(_opts: { export function getCodeForPythonFrameworkConfig({
config: DeveloperConfig config,
project: Project identifier,
deployment: Deployment prompt
identifier: string }: GetCodeForDeveloperConfigOpts): CodeSnippet {
tool?: string const mcpUrl = `${gatewayBaseUrl}/${identifier}/mcp`
}): CodeSnippet {
return { switch (config.pyFrameworkTarget) {
code: 'Python SDK is coming soon. For now, use the MCP or HTTP examples', case 'openai':
lang: 'md' return {
code: `
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-4.1",
tools=[
{
"type": "mcp",
"server_label": "${identifier}",
"server_url": "${mcpUrl}",
"require_approval": "never",
},
],
input="${prompt}",
)
print(response.output_text)
`.trim(),
lang: 'py'
}
case 'langchain':
return {
code: `
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent
client = MultiServerMCPClient(
{
"search": {
"url": "${mcpUrl}",
"transport": "streamable_http",
}
}
)
tools = await client.get_tools()
agent = create_react_agent(
"anthropic:claude-3-7-sonnet-latest",
tools
)
response = await agent.ainvoke(
{"messages": [{"role": "user", "content": "${prompt}"}]}
)`.trim(),
lang: 'py'
}
case 'llamaindex':
return {
code: `
from llama_index.llms.openai import OpenAI
from llama_index.core.agent.workflow import ReActAgent
from llama_index.core.workflow import Context
from llama_index.tools.mcp import (
get_tools_from_mcp_url,
aget_tools_from_mcp_url,
)
tools = await aget_tools_from_mcp_url("${mcpUrl}")
llm = OpenAI(model="gpt-4o-mini")
agent = ReActAgent(tools=tools, llm=llm)
ctx = Context(agent)
response = await agent.run("${prompt}", ctx=ctx)
print(str(response))
`.trim(),
lang: 'py'
}
} }
} }
@ -359,12 +434,7 @@ export function getCodeForHTTPConfig({
identifier, identifier,
deployment, deployment,
tool tool
}: { }: GetCodeForDeveloperConfigOpts): CodeSnippet {
config: DeveloperConfig
deployment: Deployment
identifier: string
tool?: string
}): CodeSnippet {
tool ??= deployment.tools[0]?.name tool ??= deployment.tools[0]?.name
assert(tool, 'tool is required') assert(tool, 'tool is required')
// TODO: need a way of getting example tool args // TODO: need a way of getting example tool args