feat(tools): added reddit hot subreddit posts tool/block

This commit is contained in:
Waleed Latif
2025-03-06 13:53:47 -08:00
parent 64ebe4ed21
commit 4d702cfdbf
6 changed files with 191 additions and 0 deletions
+58
View File
@@ -0,0 +1,58 @@
import { RedditIcon } from '@/components/icons'
import { RedditHotPostsResponse } from '@/tools/reddit/types'
import { BlockConfig } from '../types'
export const RedditBlock: BlockConfig<RedditHotPostsResponse> = {
type: 'reddit',
name: 'Reddit',
description: 'Fetch popular posts from Reddit',
longDescription:
'Access Reddit data to retrieve the most popular (hot) posts from any subreddit. Get post titles, content, authors, scores, and more.',
category: 'tools',
bgColor: '#FF5700',
icon: RedditIcon,
subBlocks: [
// Subreddit input
{
id: 'subreddit',
title: 'Subreddit',
type: 'short-input',
layout: 'full',
placeholder: 'Enter subreddit name (without r/)',
},
// Limit input
{
id: 'limit',
title: 'Number of Posts',
type: 'short-input',
layout: 'full',
placeholder: '10',
},
],
tools: {
access: ['reddit_hot_posts'],
config: {
tool: () => 'reddit_hot_posts',
},
},
inputs: {
subreddit: {
type: 'string',
required: true,
description: 'The name of the subreddit to fetch posts from (without the r/ prefix)',
},
limit: {
type: 'number',
required: false,
description: 'Maximum number of posts to return (default: 10, max: 100)',
},
},
outputs: {
response: {
type: {
subreddit: 'string',
posts: 'json',
},
},
},
}
+3
View File
@@ -13,6 +13,7 @@ import { JinaBlock } from './blocks/jina'
import { NotionBlock } from './blocks/notion'
import { OpenAIBlock } from './blocks/openai'
import { PineconeBlock } from './blocks/pinecone'
import { RedditBlock } from './blocks/reddit'
import { RouterBlock } from './blocks/router'
import { SerperBlock } from './blocks/serper'
import { SlackBlock } from './blocks/slack'
@@ -47,6 +48,7 @@ export {
PineconeBlock,
OpenAIBlock,
ExaBlock,
RedditBlock,
}
// Registry of all block configurations, alphabetically sorted
@@ -65,6 +67,7 @@ const blocks: Record<string, BlockConfig> = {
notion: NotionBlock,
openai: OpenAIBlock,
pinecone: PineconeBlock,
reddit: RedditBlock,
router: RouterBlock,
serper: SerperBlock,
slack: SlackBlock,
+19
View File
@@ -1445,3 +1445,22 @@ export function ExaAIIcon(props: SVGProps<SVGSVGElement>) {
</svg>
)
}
export function RedditIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg
{...props}
width="100px"
height="100px"
viewBox="0 0 50 50"
fill="#FFFFFF"
role="img"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M 29 3 C 26.894531 3 24.433594 4.652344 24.0625 12.03125 C 24.375 12.023438 24.683594 12 25 12 C 25.351563 12 25.714844 12.019531 26.0625 12.03125 C 26.300781 7.597656 27.355469 5 29 5 C 29.703125 5 30.101563 5.382813 30.84375 6.1875 C 31.710938 7.128906 32.84375 8.351563 35.0625 8.8125 C 35.027344 8.550781 35 8.269531 35 8 C 35 7.578125 35.042969 7.179688 35.125 6.78125 C 33.75 6.40625 33.023438 5.613281 32.3125 4.84375 C 31.519531 3.984375 30.609375 3 29 3 Z M 41 4 C 38.792969 4 37 5.796875 37 8 C 37 10.203125 38.792969 12 41 12 C 43.207031 12 45 10.203125 45 8 C 45 5.796875 43.207031 4 41 4 Z M 25 14 C 12.867188 14 3 20.179688 3 29 C 3 37.820313 12.867188 45 25 45 C 37.132813 45 47 37.820313 47 29 C 47 20.179688 37.132813 14 25 14 Z M 7.5 14.9375 C 6.039063 14.9375 4.652344 15.535156 3.59375 16.59375 C 1.871094 18.316406 1.515625 20.792969 2.5 22.84375 C 4.011719 19.917969 6.613281 17.421875 9.96875 15.5625 C 9.207031 15.175781 8.363281 14.9375 7.5 14.9375 Z M 42.5 14.9375 C 41.636719 14.9375 40.792969 15.175781 40.03125 15.5625 C 43.386719 17.421875 45.988281 19.917969 47.5 22.84375 C 48.484375 20.792969 48.128906 18.316406 46.40625 16.59375 C 45.347656 15.535156 43.960938 14.9375 42.5 14.9375 Z M 17 23 C 18.65625 23 20 24.34375 20 26 C 20 27.65625 18.65625 29 17 29 C 15.34375 29 14 27.65625 14 26 C 14 24.34375 15.34375 23 17 23 Z M 33 23 C 34.65625 23 36 24.34375 36 26 C 36 27.65625 34.65625 29 33 29 C 31.34375 29 30 27.65625 30 26 C 30 24.34375 31.34375 23 33 23 Z M 16.0625 34 C 16.3125 34.042969 16.558594 34.183594 16.71875 34.40625 C 16.824219 34.554688 19.167969 37.6875 25 37.6875 C 30.910156 37.6875 33.257813 34.46875 33.28125 34.4375 C 33.597656 33.988281 34.234375 33.867188 34.6875 34.1875 C 35.136719 34.503906 35.222656 35.109375 34.90625 35.5625 C 34.789063 35.730469 31.9375 39.6875 25 39.6875 C 18.058594 39.6875 15.210938 35.730469 15.09375 35.5625 C 14.777344 35.109375 14.859375 34.503906 15.3125 34.1875 C 15.539063 34.027344 15.8125 33.957031 16.0625 34 Z"
fill="currentColor"
/>
</svg>
)
}
+2
View File
@@ -25,6 +25,7 @@ import { generateEmbeddingsTool as pineconeGenerateEmbeddingsTool } from './pine
import { searchTextTool as pineconeSearchTextTool } from './pinecone/searchText'
import { searchVectorTool as pineconeSearchVectorTool } from './pinecone/searchVector'
import { upsertTextTool as pineconeUpsertTextTool } from './pinecone/upsertText'
import { hotPostsTool as redditHotPosts } from './reddit/hot'
import { opportunitiesTool as salesforceOpportunities } from './salesforce/opportunities'
import { searchTool as serperSearch } from './serper/search'
import { slackMessageTool } from './slack/message'
@@ -75,6 +76,7 @@ export const tools: Record<string, ToolConfig> = {
exa_get_contents: exaGetContents,
exa_find_similar_links: exaFindSimilarLinks,
exa_answer: exaAnswer,
reddit_hot_posts: redditHotPosts,
}
// Get a tool by its ID
+85
View File
@@ -0,0 +1,85 @@
import { ToolConfig, ToolResponse } from '../types'
import { RedditHotPostsResponse, RedditPost } from './types'
interface HotPostsParams {
subreddit: string
limit?: number
}
export const hotPostsTool: ToolConfig<HotPostsParams, RedditHotPostsResponse> = {
id: 'reddit_hot_posts',
name: 'Reddit Hot Posts',
description: 'Fetch the most popular (hot) posts from a specified subreddit.',
version: '1.0.0',
params: {
subreddit: {
type: 'string',
required: true,
description: 'The name of the subreddit to fetch posts from (without the r/ prefix)',
},
limit: {
type: 'number',
required: false,
description: 'Maximum number of posts to return (default: 10, max: 100)',
},
},
request: {
url: (params) =>
`https://www.reddit.com/r/${params.subreddit}/hot.json?limit=${params.limit || 10}`,
method: 'GET',
headers: () => ({
'User-Agent': 'SimStudio/1.0.0',
'Content-Type': 'application/json',
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok) {
throw new Error(data.message || 'Failed to fetch Reddit posts')
}
if (data.error) {
throw new Error(data.message || 'Reddit API error')
}
const posts: RedditPost[] = data.data.children.map((child: any) => {
const post = child.data
return {
id: post.id,
title: post.title,
author: post.author,
url: post.url,
permalink: `https://www.reddit.com${post.permalink}`,
created_utc: post.created_utc,
score: post.score,
num_comments: post.num_comments,
selftext: post.selftext,
thumbnail:
post.thumbnail !== 'self' && post.thumbnail !== 'default' ? post.thumbnail : undefined,
is_self: post.is_self,
subreddit: post.subreddit,
subreddit_name_prefixed: post.subreddit_name_prefixed,
}
})
// Extract the subreddit name from the response data
const subreddit =
data.data?.children?.[0]?.data?.subreddit || (posts.length > 0 ? posts[0].subreddit : '')
return {
success: true,
output: {
subreddit,
posts,
},
}
},
transformError: (error) => {
return error instanceof Error ? error.message : 'An error occurred while fetching Reddit posts'
},
}
+24
View File
@@ -0,0 +1,24 @@
import { ToolResponse } from '../types'
export interface RedditPost {
id: string
title: string
author: string
url: string
permalink: string
created_utc: number
score: number
num_comments: number
selftext?: string
thumbnail?: string
is_self: boolean
subreddit: string
subreddit_name_prefixed: string
}
export interface RedditHotPostsResponse extends ToolResponse {
output: {
subreddit: string
posts: RedditPost[]
}
}