kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: improve example-usage
rodzic
7b5f7e8f97
commit
591a5d65c3
|
@ -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>
|
||||||
|
|
|
@ -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 />
|
||||||
|
|
|
@ -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>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 (
|
||||||
|
|
|
@ -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
|
||||||
|
|
Ładowanie…
Reference in New Issue