feat: improve web examples

pull/715/head
Travis Fischer 2025-06-24 20:06:20 -05:00
rodzic 7759aa43d3
commit 7b5f7e8f97
10 zmienionych plików z 391 dodań i 89 usunięć

Wyświetl plik

@ -79,7 +79,10 @@ export function registerV1CreateDeployment(
if (!project) { if (!project) {
// Used for testing e2e fixtures in the development marketplace // Used for testing e2e fixtures in the development marketplace
const isPrivate = !(user.username === 'dev' && env.isDev) const isPrivate = !(
(user.username === 'dev' && env.isDev) ||
user.username === 'agentic'
)
// Upsert the project if it doesn't already exist // Upsert the project if it doesn't already exist
// The typecast is necessary here because we're not populating the // The typecast is necessary here because we're not populating the

Wyświetl plik

@ -63,7 +63,10 @@ export function registerV1CreateProject(
) )
// Used for testing e2e fixtures in the development marketplace // Used for testing e2e fixtures in the development marketplace
const isPrivate = !(user.username === 'dev' && env.isDev) const isPrivate = !(
(user.username === 'dev' && env.isDev) ||
user.username === 'agentic'
)
const [project] = await db const [project] = await db
.insert(schema.projects) .insert(schema.projects)

Wyświetl plik

@ -1,7 +1,5 @@
import { sha256 } from '@agentic/platform-core' import { sha256 } from '@agentic/platform-core'
export async function createConsumerToken(): Promise<string> { export async function createConsumerToken(): Promise<string> {
const hash = await sha256() return sha256()
return hash.slice(0, 24)
} }

Wyświetl plik

@ -1,11 +1,10 @@
import Link from 'next/link' import Link from 'next/link'
import { DemandSideCTA } from '@/components/demand-side-cta' import { DemandSideCTA } from '@/components/demand-side-cta'
import { ExampleUsage } from '@/components/example-usage'
import { GitHubStarCounter } from '@/components/github-star-counter' import { GitHubStarCounter } from '@/components/github-star-counter'
import { githubUrl, twitterUrl } from '@/lib/config' import { githubUrl, twitterUrl } from '@/lib/config'
import { ExampleUsage } from './example-usage'
export default function TheBestDamnLandingPageEver() { export default function TheBestDamnLandingPageEver() {
return ( return (
<> <>

Wyświetl plik

@ -1,9 +1,21 @@
import { toJsxRuntime } from 'hast-util-to-jsx-runtime' import { toJsxRuntime } from 'hast-util-to-jsx-runtime'
import { Fragment, type JSX, useEffect, useState } from 'react' import { CheckIcon, CopyIcon } from 'lucide-react'
import {
Fragment,
type JSX,
useCallback,
useEffect,
useRef,
useState
} from 'react'
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 { toastError } from '@/lib/notifications'
import { cn } from '@/lib/utils'
import { LoadingIndicator } from './loading-indicator' import { LoadingIndicator } from './loading-indicator'
import { Button } from './ui/button'
export async function highlight({ export async function highlight({
code, code,
@ -51,10 +63,62 @@ export function CodeBlock({
className?: string className?: string
}) { }) {
const [nodes, setNodes] = useState(initial) const [nodes, setNodes] = useState(initial)
const [isCopied, setIsCopied] = useState(false)
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)
useEffect(() => { useEffect(() => {
void highlight({ code, lang, theme, className }).then(setNodes) void highlight({
}, [code, lang, theme, className]) code,
lang,
theme,
className: 'rounded-sm w-full text-wrap p-4 text-sm'
}).then(setNodes)
}, [code, lang, theme])
return nodes ?? <LoadingIndicator /> const onCopy = useCallback(() => {
;(async () => {
try {
await navigator.clipboard.writeText(code)
setIsCopied(true)
if (timeoutRef.current) {
clearTimeout(timeoutRef.current)
timeoutRef.current = null
}
timeoutRef.current = setTimeout(() => {
timeoutRef.current = null
setIsCopied(false)
}, 2000)
} catch {
setIsCopied(true)
if (timeoutRef.current) {
clearTimeout(timeoutRef.current)
timeoutRef.current = null
}
void toastError('Error copying code to clipboard')
}
})()
}, [code, timeoutRef])
return (
<div className={cn('relative group rounded-sm w-full', className)}>
{nodes ? (
<>
{nodes}
<Button
variant='outline'
className='absolute top-4 right-4 px-2.5! opacity-0 group-hover:opacity-100 group-hover:duration-0 transition-opacity duration-150'
onClick={onCopy}
>
{isCopied ? <CheckIcon /> : <CopyIcon />}
</Button>
</>
) : (
<LoadingIndicator />
)}
</div>
)
} }

Wyświetl plik

@ -2,11 +2,13 @@
import { useLocalStorage } from 'react-use' import { useLocalStorage } from 'react-use'
import { useAgentic } from '@/components/agentic-provider'
import { CodeBlock } from '@/components/code-block' import { CodeBlock } from '@/components/code-block'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { import {
defaultConfig, defaultConfig,
type DeveloperConfig, type DeveloperConfig,
getCodeForDeveloperConfig,
type HTTPTarget, type HTTPTarget,
httpTargetLabels, httpTargetLabels,
httpTargets, httpTargets,
@ -23,16 +25,85 @@ import {
tsFrameworkTargetLabels, tsFrameworkTargetLabels,
tsFrameworkTargets tsFrameworkTargets
} from '@/lib/developer-config' } from '@/lib/developer-config'
import { useQuery } from '@/lib/query-client'
import { LoadingIndicator } from './loading-indicator'
export function ExampleUsage() { export function ExampleUsage() {
const ctx = useAgentic()
const [config, setConfig] = useLocalStorage<DeveloperConfig>( const [config, setConfig] = useLocalStorage<DeveloperConfig>(
'config', 'config',
defaultConfig defaultConfig
) )
// TODO: make this configurable
// 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)
const projectIdentifier = '@agentic/search'
// Load the public project
const {
data: project,
isLoading,
isError
} = useQuery({
queryKey: ['project', projectIdentifier],
queryFn: () =>
ctx!.api.getPublicProjectByIdentifier({
projectIdentifier,
populate: ['lastPublishedDeployment']
}),
enabled: !!ctx
})
// If the user is authenticated, check if they have an active subscription to
// this project
// TODO: use consumer for apiKey
// const {
// data: consumer,
// isLoading: isConsumerLoading
// // isError: isConsumerError
// } = useQuery({
// queryKey: [
// 'project',
// projectIdentifier,
// 'user',
// ctx?.api.authSession?.user.id
// ],
// queryFn: () =>
// ctx!.api.getConsumerByProjectIdentifier({
// projectIdentifier
// }),
// enabled: !!ctx?.isAuthenticated
// })
if (isLoading || !config) {
return <LoadingIndicator className='w-full max-w-3xl' />
}
// TODO: allow to target a specific deployment
const deployment = project?.lastPublishedDeployment
if (isError || !project || !deployment) {
return (
<div>
Error loading project. Please refresh the page or contact{' '}
<a href='mailto:support@agentic.so'>support@agentic.so</a>.
</div>
)
}
const codeSnippet = getCodeForDeveloperConfig({
config,
project,
deployment,
identifier: projectIdentifier
})
return ( return (
<Tabs <Tabs
defaultValue={config!.target} defaultValue={config.target}
onValueChange={(value) => onValueChange={(value) =>
setConfig({ setConfig({
...defaultConfig, ...defaultConfig,
@ -40,7 +111,7 @@ export function ExampleUsage() {
target: value as Target target: value as Target
}) })
} }
className='w-full max-w-2xl' className='w-full max-w-3xl'
> >
<TabsList> <TabsList>
{targets.map((target) => ( {targets.map((target) => (
@ -52,7 +123,7 @@ export function ExampleUsage() {
<TabsContent value='mcp' className='w-full'> <TabsContent value='mcp' className='w-full'>
<Tabs <Tabs
defaultValue={config!.mcpClientTarget} defaultValue={config.mcpClientTarget}
onValueChange={(value) => onValueChange={(value) =>
setConfig({ setConfig({
...defaultConfig, ...defaultConfig,
@ -80,11 +151,7 @@ export function ExampleUsage() {
value={mcpClientTarget} value={mcpClientTarget}
className='w-full' className='w-full'
> >
<CodeBlock <CodeBlock code={codeSnippet.code} lang={codeSnippet.lang} />
code={JSON.stringify(config, null, 2)}
lang='json'
className='p-4 rounded-sm w-full'
/>
</TabsContent> </TabsContent>
))} ))}
</Tabs> </Tabs>
@ -92,7 +159,7 @@ export function ExampleUsage() {
<TabsContent value='typescript' className='w-full'> <TabsContent value='typescript' className='w-full'>
<Tabs <Tabs
defaultValue={config!.tsFrameworkTarget ?? 'ai'} defaultValue={config.tsFrameworkTarget ?? 'ai'}
onValueChange={(value) => onValueChange={(value) =>
setConfig({ setConfig({
...defaultConfig, ...defaultConfig,
@ -102,12 +169,12 @@ export function ExampleUsage() {
} }
className='w-full' className='w-full'
> >
<TabsList className='h-auto flex-wrap'> <TabsList className='w-full h-auto flex-wrap'>
{tsFrameworkTargets.map((framework) => ( {tsFrameworkTargets.map((framework) => (
<TabsTrigger <TabsTrigger
key={framework} key={framework}
value={framework} value={framework}
className='cursor-pointer' className='cursor-pointer text-xs!'
> >
{tsFrameworkTargetLabels[framework]} {tsFrameworkTargetLabels[framework]}
</TabsTrigger> </TabsTrigger>
@ -116,11 +183,7 @@ export function ExampleUsage() {
{tsFrameworkTargets.map((framework) => ( {tsFrameworkTargets.map((framework) => (
<TabsContent key={framework} value={framework} className='w-full'> <TabsContent key={framework} value={framework} className='w-full'>
<CodeBlock <CodeBlock code={codeSnippet.code} lang={codeSnippet.lang} />
code={JSON.stringify(config, null, 2)}
lang='ts'
className='p-4 rounded-sm w-full'
/>
</TabsContent> </TabsContent>
))} ))}
</Tabs> </Tabs>
@ -128,7 +191,7 @@ export function ExampleUsage() {
<TabsContent value='python' className='w-full'> <TabsContent value='python' className='w-full'>
<Tabs <Tabs
defaultValue={config!.pyFrameworkTarget} defaultValue={config.pyFrameworkTarget}
onValueChange={(value) => onValueChange={(value) =>
setConfig({ setConfig({
...defaultConfig, ...defaultConfig,
@ -152,11 +215,7 @@ export function ExampleUsage() {
{pyFrameworkTargets.map((framework) => ( {pyFrameworkTargets.map((framework) => (
<TabsContent key={framework} value={framework} className='w-full'> <TabsContent key={framework} value={framework} className='w-full'>
<CodeBlock <CodeBlock code={codeSnippet.code} lang={codeSnippet.lang} />
code={JSON.stringify(config, null, 2)}
lang='py'
className='p-4 rounded-sm w-full'
/>
</TabsContent> </TabsContent>
))} ))}
</Tabs> </Tabs>
@ -164,7 +223,7 @@ export function ExampleUsage() {
<TabsContent value='http' className='w-full'> <TabsContent value='http' className='w-full'>
<Tabs <Tabs
defaultValue={config!.httpTarget} defaultValue={config.httpTarget}
onValueChange={(value) => onValueChange={(value) =>
setConfig({ setConfig({
...defaultConfig, ...defaultConfig,
@ -188,11 +247,7 @@ export function ExampleUsage() {
{httpTargets.map((httpTarget) => ( {httpTargets.map((httpTarget) => (
<TabsContent key={httpTarget} value={httpTarget} className='w-full'> <TabsContent key={httpTarget} value={httpTarget} className='w-full'>
<CodeBlock <CodeBlock code={codeSnippet.code} lang={codeSnippet.lang} />
code={JSON.stringify(config, null, 2)}
lang='bash'
className='p-4 rounded-sm w-full'
/>
</TabsContent> </TabsContent>
))} ))}
</Tabs> </Tabs>

Wyświetl plik

@ -5,6 +5,7 @@
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
margin: 0 auto;
} }
.fill { .fill {

Wyświetl plik

@ -1,4 +1,5 @@
import type { Deployment, Project } from '@agentic/platform-types' import type { Deployment, Project } from '@agentic/platform-types'
import type { BundledLanguage } from 'shiki/bundle/web'
import { assert } from '@agentic/platform-core' import { assert } from '@agentic/platform-core'
import { gatewayBaseUrl } from './config' import { gatewayBaseUrl } from './config'
@ -24,7 +25,7 @@ export const httpTargets: (keyof typeof httpTargetLabels)[] = Object.keys(
export type HTTPTarget = (typeof httpTargets)[number] export type HTTPTarget = (typeof httpTargets)[number]
export const mcpClientTargetLabels = { export const mcpClientTargetLabels = {
any: 'Any MCP Client', url: 'MCP Server URL',
'claude-desktop': 'Claude Desktop', 'claude-desktop': 'Claude Desktop',
raycast: 'Raycast', raycast: 'Raycast',
cursor: 'Cursor', cursor: 'Cursor',
@ -41,8 +42,8 @@ export const tsFrameworkTargetLabels = {
'openai-chat': 'OpenAI Chat', 'openai-chat': 'OpenAI Chat',
'openai-responses': 'OpenAI Responses', 'openai-responses': 'OpenAI Responses',
langchain: 'LangChain', langchain: 'LangChain',
mastra: 'Mastra',
llamaindex: 'LlamaIndex', llamaindex: 'LlamaIndex',
mastra: 'Mastra',
'firebase-genkit': 'Firebase GenKit', 'firebase-genkit': 'Firebase GenKit',
xsai: 'xsAI' xsai: 'xsAI'
} as const } as const
@ -69,19 +70,25 @@ export type DeveloperConfig = {
export const defaultConfig: DeveloperConfig = { export const defaultConfig: DeveloperConfig = {
target: 'typescript', target: 'typescript',
mcpClientTarget: 'any', mcpClientTarget: 'url',
tsFrameworkTarget: 'ai', tsFrameworkTarget: 'ai',
pyFrameworkTarget: 'openai', pyFrameworkTarget: 'openai',
httpTarget: 'curl' httpTarget: 'curl'
} }
export type CodeSnippet = {
code: string
lang: BundledLanguage
// install?: string // TODO
}
export function getCodeForDeveloperConfig(opts: { export function getCodeForDeveloperConfig(opts: {
config: DeveloperConfig config: DeveloperConfig
project: Project project: Project
deployment: Deployment deployment: Deployment
identifier: string identifier: string
tool?: string tool?: string
}): string { }): CodeSnippet {
const { config } = opts const { config } = opts
switch (config.target) { switch (config.target) {
@ -90,8 +97,7 @@ export function getCodeForDeveloperConfig(opts: {
case 'typescript': case 'typescript':
return getCodeForTSFrameworkConfig(opts) return getCodeForTSFrameworkConfig(opts)
case 'python': case 'python':
return 'Python support is coming soon...' return getCodeForPythonFrameworkConfig(opts)
// return getCodeForPythonFrameworkConfig(opts)
case 'http': case 'http':
return getCodeForHTTPConfig(opts) return getCodeForHTTPConfig(opts)
} }
@ -101,21 +107,27 @@ export function getCodeForMCPClientConfig({
identifier identifier
}: { }: {
identifier: string identifier: string
}): string { }): CodeSnippet {
return `${gatewayBaseUrl}/${identifier}/mcp` return {
code: `${gatewayBaseUrl}/${identifier}/mcp`,
lang: 'bash'
}
} }
export function getCodeForTSFrameworkConfig({ export function getCodeForTSFrameworkConfig({
config, config,
identifier identifier,
prompt = 'What is the latest news about AI?'
}: { }: {
config: DeveloperConfig config: DeveloperConfig
identifier: string identifier: string
}): string { prompt?: string
}): CodeSnippet {
switch (config.tsFrameworkTarget) { switch (config.tsFrameworkTarget) {
case 'ai': case 'ai':
return ` return {
import { createAISDKTools } from '@agentic/ai' code: `
import { createAISDKTools } from '@agentic/ai-sdk'
import { AgenticToolClient } from '@agentic/platform-tool-client' import { AgenticToolClient } from '@agentic/platform-tool-client'
import { openai } from '@ai-sdk/openai' import { openai } from '@ai-sdk/openai'
import { generateText } from 'ai' import { generateText } from 'ai'
@ -126,66 +138,221 @@ const result = await generateText({
model: openai('gpt-4o-mini'), model: openai('gpt-4o-mini'),
tools: createAISDKTools(searchTool), tools: createAISDKTools(searchTool),
toolChoice: 'required', toolChoice: 'required',
temperature: 0, prompt: '${prompt}'
system: 'You are a helpful assistant. Be as concise as possible.',
prompt: 'What is the latest news about AI?'
}) })
console.log(result.toolResults[0]) console.log(result.toolResults[0])
`.trim() `.trim(),
lang: 'ts'
}
case 'openai-chat': case 'openai-chat':
return ` return {
code: `
import { AgenticToolClient } from '@agentic/platform-tool-client' import { AgenticToolClient } from '@agentic/platform-tool-client'
import OpenAI from 'openai' import OpenAI from 'openai'
const openai = new OpenAI() const openai = new OpenAI()
const searchTool = await AgenticToolClient.fromIdentifier('${identifier}') const searchTool = await AgenticToolClient.fromIdentifier('${identifier}')
// This example uses OpenAI's Chat Completions API
const res = await openai.chat.completions.create({ const res = await openai.chat.completions.create({
model: 'gpt-4o-mini',
messages: [ messages: [
{
role: 'system',
content: 'You are a helpful assistant. Be as concise as possible.'
}
{ {
role: 'user', role: 'user',
content: 'What is the latest news about AI?' content: '${prompt}'
} }
], ],
model: 'gpt-4o-mini',
temperature: 0,
tools: searchTool.functions.toolSpecs, tools: searchTool.functions.toolSpecs,
tool_choice: 'required' tool_choice: 'required'
}) })
const message = res.choices[0]!.message! const message = res.choices[0]!.message!
const toolCall = message.tool_calls![0]! const toolCall = message.tool_calls![0]!.function!
const toolResult = await searchTool.callTool(toolCall.name, toolCall.arguments)
const tool = searchTool.functions.get(toolCall.function.name)!
const toolResult = await tool(toolCall.function.arguments)
console.log(toolResult) console.log(toolResult)
`.trim() `.trim(),
lang: 'ts'
} }
return '' case 'openai-responses':
return {
code: `
import { AgenticToolClient } from '@agentic/platform-tool-client'
import OpenAI from 'openai'
const openai = new OpenAI()
const searchTool = await AgenticToolClient.fromIdentifier('${identifier}')
// This example uses OpenAI's newer Responses API
const res = await openai.responses.create({
model: 'gpt-4o-mini',
tools: searchTool.functions.responsesToolSpecs,
tool_choice: 'required',
input: [
{
role: 'user',
content: '${prompt}'
}
]
})
const toolCall = res.output[0]
const toolResult = await searchTool.callTool(toolCall.name, toolCall.arguments)
console.log(toolResult)
`.trim(),
lang: 'ts'
}
case 'langchain':
return {
code: `
import { createLangChainTools } from '@agentic/langchain'
import { AgenticToolClient } from '@agentic/platform-tool-client'
import { ChatPromptTemplate } from '@langchain/core/prompts'
import { ChatOpenAI } from '@langchain/openai'
import { AgentExecutor, createToolCallingAgent } from 'langchain/agents'
const searchTool = await AgenticToolClient.fromIdentifier('${identifier}')
const agent = createToolCallingAgent({
llm: new ChatOpenAI({ model: 'gpt-4o-mini' }),
tools: createLangChainTools(searchTool),
prompt: ChatPromptTemplate.fromMessages([
['placeholder', '{chat_history}'],
['human', '{input}'],
['placeholder', '{agent_scratchpad}']
])
})
const agentExecutor = new AgentExecutor({ agent, tools })
const result = await agentExecutor.invoke({
input: '${prompt}'
})
console.log(result.output)
`.trim(),
lang: 'ts'
}
case 'llamaindex':
return {
code: `
import { createLlamaIndexTools } from '@agentic/llamaindex'
import { AgenticToolClient } from '@agentic/platform-tool-client'
import { openai } from '@llamaindex/openai'
import { agent } from '@llamaindex/workflow'
const searchTool = await AgenticToolClient.fromIdentifier('${identifier}')
const exampleAgent = agent({
llm: openai({ model: 'gpt-4o-mini', temperature: 0 }),
tools: createLlamaIndexTools(searchTool)
})
const response = await exampleAgent.run(
'${prompt}'
)
console.log(response.data.result)
`.trim(),
lang: 'ts'
}
case 'mastra':
return {
code: `
import { createMastraTools } from '@agentic/mastra'
import { AgenticToolClient } from '@agentic/platform-tool-client'
import { openai } from '@ai-sdk/openai'
import { Agent } from '@mastra/core/agent'
const searchTool = await AgenticToolClient.fromIdentifier('${identifier}')
const exampleAgent = new Agent({
name: 'Example Agent',
model: openai('gpt-4o-mini') as any,
instructions: 'You are a helpful assistant. Be as concise as possible.',
tools: createMastraTools(searchTool)
})
const res = await exampleAgent.generate(
'${prompt}'
)
console.log(res.text)`.trim(),
lang: 'ts'
}
case 'firebase-genkit':
return {
code: `
import { createGenkitTools } from '@agentic/genkit'
import { AgenticToolClient } from '@agentic/platform-tool-client'
import { genkit } from 'genkit'
import { gpt4oMini, openAI } from 'genkitx-openai'
const searchTool = await AgenticToolClient.fromIdentifier('${identifier}')
const ai = genkit({
plugins: [openAI()]
})
const result = await ai.generate({
model: gpt4oMini,
tools: createGenkitTools(ai, searchTool),
prompt: '${prompt}'
})
console.log(result)`.trim(),
lang: 'ts'
}
case 'xsai':
return {
code: `
import { AgenticToolClient } from '@agentic/platform-tool-client'
import { createXSAITools } from '@agentic/xsai'
import { generateText } from 'xsai'
const searchTool = await AgenticToolClient.fromIdentifier('${identifier}')
const result = await generateText({
apiKey: process.env.OPENAI_API_KEY!,
baseURL: 'https://api.openai.com/v1/',
model: 'gpt-4o-mini',
tools: await createXSAITools(searchTool),
toolChoice: 'required',
messages: [
{
role: 'user',
content: '${prompt}'
}
]
})
console.log(JSON.stringify(result, null, 2))`.trim(),
lang: 'ts'
}
}
} }
// export function getCodeForPythonFrameworkConfig({ export function getCodeForPythonFrameworkConfig(_opts: {
// config, config: DeveloperConfig
// project, project: Project
// deployment, deployment: Deployment
// tool identifier: string
// }: { tool?: string
// config: DeveloperConfig }): CodeSnippet {
// project: Project return {
// deployment: Deployment code: 'Python SDK is coming soon. For now, use the MCP or HTTP examples',
// identifier: string lang: 'md'
// tool?: string }
// }): string { }
// return ''
// }
export function getCodeForHTTPConfig({ export function getCodeForHTTPConfig({
config, config,
@ -197,7 +364,7 @@ export function getCodeForHTTPConfig({
deployment: Deployment deployment: Deployment
identifier: string identifier: string
tool?: string tool?: string
}): 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
@ -206,9 +373,15 @@ export function getCodeForHTTPConfig({
switch (config.httpTarget) { switch (config.httpTarget) {
case 'curl': case 'curl':
return `curl -X POST -H "Content-Type: application/json" -d '{"query": "example google search"}' ${url}` return {
code: `curl -X POST -H "Content-Type: application/json" -d '{"query": "example google search"}' ${url}`,
lang: 'bash'
}
case 'httpie': case 'httpie':
return `http -j ${url} query='example google search'` return {
code: `http -j ${url} query='example google search'`,
lang: 'bash'
}
} }
} }

Wyświetl plik

@ -73,6 +73,12 @@ export class AgenticToolClient extends AIFunctionsProvider {
return this._functions return this._functions
} }
async callTool(toolName: string, args: string | Record<string, any>) {
const tool = this.functions.get(toolName)
assert(tool, `Tool "${toolName}" not found`)
return tool(typeof args === 'string' ? args : JSON.stringify(args))
}
/** /**
* Creates an Agentic tool client from a project or deployment identifier. * Creates an Agentic tool client from a project or deployment identifier.
* *
@ -84,8 +90,6 @@ export class AgenticToolClient extends AIFunctionsProvider {
* @example * @example
* ```ts * ```ts
* const searchTool = await AgenticToolClient.fromIdentifier('@agentic/search') * const searchTool = await AgenticToolClient.fromIdentifier('@agentic/search')
* const searchToolV1 = await AgenticToolClient.fromIdentifier('@agentic/search@v1.0.0')
* const searchToolLatest = await AgenticToolClient.fromIdentifier('@agentic/search@latest')
* ``` * ```
*/ */
static async fromIdentifier( static async fromIdentifier(

Wyświetl plik

@ -43,6 +43,8 @@
- consider using [neon serverless driver](https://orm.drizzle.team/docs/connect-neon) for production - consider using [neon serverless driver](https://orm.drizzle.team/docs/connect-neon) for production
- can this also be used locally? - can this also be used locally?
- may need to update our `drizzle-orm` fork - may need to update our `drizzle-orm` fork
- simplify `AgenticToolClient` and only require one package per TS LLM SDK
- `createAISDKToolsFromIdentifier(projectIdentifier)`
## TODO: Post-MVP ## TODO: Post-MVP