mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-09 15:07:55 -05:00
Added youtube search tool/block
This commit is contained in:
57
blocks/blocks/youtube.ts
Normal file
57
blocks/blocks/youtube.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { YouTubeIcon } from '@/components/icons'
|
||||
import { YouTubeSearchResponse } from '@/tools/youtube/search'
|
||||
import { BlockConfig } from '../types'
|
||||
|
||||
export const YouTubeSearchBlock: BlockConfig<YouTubeSearchResponse> = {
|
||||
type: 'youtube_search',
|
||||
toolbar: {
|
||||
title: 'YouTube Search',
|
||||
description: 'Search for videos on YouTube',
|
||||
bgColor: '#FF0000',
|
||||
icon: YouTubeIcon,
|
||||
category: 'tools',
|
||||
},
|
||||
tools: {
|
||||
access: ['youtube_search'],
|
||||
},
|
||||
workflow: {
|
||||
inputs: {
|
||||
apiKey: { type: 'string', required: true },
|
||||
query: { type: 'string', required: true },
|
||||
maxResults: { type: 'number', required: false },
|
||||
},
|
||||
outputs: {
|
||||
response: {
|
||||
type: {
|
||||
items: 'json',
|
||||
totalResults: 'number',
|
||||
},
|
||||
},
|
||||
},
|
||||
subBlocks: [
|
||||
{
|
||||
id: 'query',
|
||||
title: 'Search Query',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Enter search query',
|
||||
},
|
||||
{
|
||||
id: 'apiKey',
|
||||
title: 'YouTube API Key',
|
||||
type: 'short-input',
|
||||
layout: 'full',
|
||||
placeholder: 'Enter YouTube API Key',
|
||||
password: true,
|
||||
},
|
||||
{
|
||||
id: 'maxResults',
|
||||
title: 'Max Results',
|
||||
type: 'slider',
|
||||
layout: 'half',
|
||||
min: 0,
|
||||
max: 20,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import { SerperBlock } from './blocks/serper'
|
||||
import { SlackMessageBlock } from './blocks/slack'
|
||||
import { TavilyExtractBlock, TavilySearchBlock } from './blocks/tavily'
|
||||
import { TranslateBlock } from './blocks/translate'
|
||||
import { YouTubeSearchBlock } from './blocks/youtube'
|
||||
import { BlockConfig } from './types'
|
||||
|
||||
// Export blocks for ease of use
|
||||
@@ -30,6 +31,7 @@ export {
|
||||
TavilySearchBlock,
|
||||
TavilyExtractBlock,
|
||||
RouterBlock,
|
||||
YouTubeSearchBlock,
|
||||
}
|
||||
|
||||
// Registry of all block configurations
|
||||
@@ -48,6 +50,7 @@ const blocks: Record<string, BlockConfig> = {
|
||||
serper_search: SerperBlock,
|
||||
tavily_search: TavilySearchBlock,
|
||||
tavily_extract: TavilyExtractBlock,
|
||||
youtube_search: YouTubeSearchBlock,
|
||||
}
|
||||
|
||||
// Build a reverse mapping of tools to block types
|
||||
|
||||
@@ -1124,4 +1124,19 @@ export const ConnectIcon = (props: SVGProps<SVGSVGElement>) => (
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
)
|
||||
|
||||
export function YouTubeIcon(props: React.SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="#FFFFFF"
|
||||
{...props}
|
||||
>
|
||||
<title>YouTube</title>
|
||||
<path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z" />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -21,6 +21,12 @@ import { cn } from '@/lib/utils'
|
||||
// This file is not typed correctly from shadcn, so we're disabling the type checker
|
||||
// @ts-nocheck
|
||||
|
||||
// This file is not typed correctly from shadcn, so we're disabling the type checker
|
||||
// @ts-nocheck
|
||||
|
||||
// This file is not typed correctly from shadcn, so we're disabling the type checker
|
||||
// @ts-nocheck
|
||||
|
||||
const Command = React.forwardRef<
|
||||
React.ElementRef<typeof CommandPrimitive>,
|
||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive> & {
|
||||
|
||||
@@ -17,36 +17,9 @@ import { extractTool as tavilyExtract } from './tavily/extract'
|
||||
import { searchTool as tavilySearch } from './tavily/search'
|
||||
import { ToolConfig, ToolResponse } from './types'
|
||||
import { chatTool as xaiChat } from './xai/chat'
|
||||
import { youtubeSearchTool } from './youtube/search'
|
||||
|
||||
/**
|
||||
* Registry of all available tools. Each tool is designed for specific use cases:
|
||||
*
|
||||
* AI Model Tools:
|
||||
* - openai_chat: Advanced language model for general conversation, reasoning, and task completion
|
||||
* - anthropic_chat: Claude model specialized in detailed analysis and complex reasoning
|
||||
* - google_chat: PaLM model for general conversation and task assistance
|
||||
* - xai_chat: Specialized AI model for explainable AI interactions
|
||||
* - deepseek_chat: Code-specialized language model for programming tasks
|
||||
* - deepseek_reasoner: Advanced reasoning model for complex problem-solving
|
||||
*
|
||||
* Web & Data Tools:
|
||||
* - http_request: Make HTTP requests to any API endpoint with custom headers and body
|
||||
* - firecrawl_scrape: Extract structured data from web pages with advanced scraping
|
||||
* - jina_readurl: Efficiently read and parse content from web URLs
|
||||
* - serper_search: Perform web searches with high-quality, structured results
|
||||
* - tavily_search: AI-powered web search with comprehensive results
|
||||
* - tavily_extract: Extract specific information from web content
|
||||
*
|
||||
* Business Integration Tools:
|
||||
* - hubspot_contacts: Manage and query HubSpot CRM contacts
|
||||
* - salesforce_opportunities: Handle Salesforce sales opportunities
|
||||
* - slack_message: Send messages to Slack channels or users
|
||||
* - github_repoinfo: Fetch detailed information about GitHub repositories
|
||||
*
|
||||
* Utility Tools:
|
||||
* - function_execute: Execute custom JavaScript functions with provided parameters
|
||||
* - crewai_vision: Process and analyze images with AI capabilities
|
||||
*/
|
||||
// Registry of all available tools
|
||||
export const tools: Record<string, ToolConfig> = {
|
||||
// AI Models
|
||||
openai_chat: openAIChat,
|
||||
@@ -76,6 +49,7 @@ export const tools: Record<string, ToolConfig> = {
|
||||
serper_search: serperSearch,
|
||||
tavily_search: tavilySearch,
|
||||
tavily_extract: tavilyExtract,
|
||||
youtube_search: youtubeSearchTool,
|
||||
}
|
||||
|
||||
// Get a tool by its ID
|
||||
|
||||
89
tools/youtube/search.ts
Normal file
89
tools/youtube/search.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import { ToolConfig, ToolResponse } from '../types'
|
||||
|
||||
export interface YouTubeSearchParams {
|
||||
apiKey: string
|
||||
query: string
|
||||
maxResults?: number
|
||||
pageToken?: string
|
||||
}
|
||||
|
||||
export interface YouTubeSearchResponse extends ToolResponse {
|
||||
output: {
|
||||
items: Array<{
|
||||
videoId: string
|
||||
title: string
|
||||
description: string
|
||||
thumbnail: string
|
||||
}>
|
||||
totalResults: number
|
||||
nextPageToken?: string
|
||||
}
|
||||
}
|
||||
|
||||
export const youtubeSearchTool: ToolConfig<YouTubeSearchParams, YouTubeSearchResponse> = {
|
||||
id: 'youtube_search',
|
||||
name: 'YouTube Search',
|
||||
description: 'Search for videos on YouTube using the YouTube Data API.',
|
||||
version: '1.0.0',
|
||||
params: {
|
||||
query: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'Search query for YouTube videos',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
requiredForToolCall: true,
|
||||
description: 'YouTube API Key',
|
||||
},
|
||||
maxResults: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
default: 5,
|
||||
description: 'Maximum number of videos to return',
|
||||
},
|
||||
},
|
||||
request: {
|
||||
url: (params: YouTubeSearchParams) => {
|
||||
let url = `https://www.googleapis.com/youtube/v3/search?part=snippet&type=video&key=${params.apiKey}&q=${encodeURIComponent(
|
||||
params.query
|
||||
)}`
|
||||
url += `&maxResults=${params.maxResults || 5}`
|
||||
return url
|
||||
},
|
||||
method: 'GET',
|
||||
headers: () => ({
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
},
|
||||
transformResponse: async (response: Response): Promise<YouTubeSearchResponse> => {
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
throw new Error(data.error?.message || 'YouTube API error')
|
||||
}
|
||||
const items = (data.items || []).map((item: any) => ({
|
||||
videoId: item.id?.videoId,
|
||||
title: item.snippet?.title,
|
||||
description: item.snippet?.description,
|
||||
thumbnail:
|
||||
item.snippet?.thumbnails?.default?.url ||
|
||||
item.snippet?.thumbnails?.medium?.url ||
|
||||
item.snippet?.thumbnails?.high?.url ||
|
||||
'',
|
||||
}))
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
items,
|
||||
totalResults: data.pageInfo?.totalResults || 0,
|
||||
nextPageToken: data.nextPageToken,
|
||||
},
|
||||
}
|
||||
},
|
||||
transformError: (error: any): string => {
|
||||
const message = error.error?.message || error.message || 'YouTube search failed'
|
||||
const code = error.error?.code || error.code
|
||||
return `${message} (${code})`
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user