feat(tools): added additional reddit tools, docs

This commit is contained in:
Waleed Latif
2025-04-28 14:13:15 -07:00
parent b2e583cbc8
commit a769c31626
7 changed files with 481 additions and 15 deletions
+49 -3
View File
@@ -1,6 +1,6 @@
---
title: Reddit
description: Fetch popular posts from Reddit
description: Access Reddit data and content
---
import { BlockInfoCard } from "@/components/ui/block-info-card"
@@ -44,7 +44,7 @@ In Sim Studio, the Reddit integration enables your agents to programmatically ac
## Usage Instructions
Access Reddit data to retrieve the most popular (hot) posts from any subreddit. Get post titles, content, authors, scores, and more.
Access Reddit data to retrieve posts and comments from any subreddit. Get post titles, content, authors, scores, comments and more.
@@ -67,6 +67,50 @@ Fetch the most popular (hot) posts from a specified subreddit.
| --------- | ---- |
| `subreddit` | string |
### `reddit_get_posts`
Fetch posts from a subreddit with different sorting options
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `subreddit` | string | Yes | The name of the subreddit to fetch posts from \(without the r/ prefix\) |
| `sort` | string | No | Sort method for posts: |
| `limit` | number | No | Maximum number of posts to return \(default: 10, max: 100\) |
| `time` | string | No | Time filter for |
#### Output
| Parameter | Type |
| --------- | ---- |
| `subreddit` | string |
### `reddit_get_comments`
Fetch comments from a specific Reddit post
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `postId` | string | Yes | The ID of the Reddit post to fetch comments from |
| `subreddit` | string | Yes | The subreddit where the post is located \(without the r/ prefix\) |
| `sort` | string | No | Sort method for comments: |
| `limit` | number | No | Maximum number of comments to return \(default: 50, max: 100\) |
#### Output
| Parameter | Type |
| --------- | ---- |
| `post` | string |
| `title` | string |
| `author` | string |
| `selftext` | string |
| `created_utc` | string |
| `score` | string |
| `permalink` | string |
## Block Configuration
@@ -75,7 +119,7 @@ Fetch the most popular (hot) posts from a specified subreddit.
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `subreddit` | string | No | Subreddit - Enter subreddit name \(without r/\) |
| `action` | string | No | Action |
@@ -86,6 +130,8 @@ Fetch the most popular (hot) posts from a specified subreddit.
| `response` | object | Output from response |
| ↳ `subreddit` | string | subreddit of the response |
| ↳ `posts` | json | posts of the response |
| ↳ `post` | json | post of the response |
| ↳ `comments` | json | comments of the response |
## Notes
+171 -11
View File
@@ -1,57 +1,217 @@
import { RedditIcon } from '@/components/icons'
import { RedditHotPostsResponse } from '@/tools/reddit/types'
import { RedditHotPostsResponse, RedditPostsResponse, RedditCommentsResponse } from '@/tools/reddit/types'
import { BlockConfig } from '../types'
export const RedditBlock: BlockConfig<RedditHotPostsResponse> = {
export const RedditBlock: BlockConfig<RedditHotPostsResponse | RedditPostsResponse | RedditCommentsResponse> = {
type: 'reddit',
name: 'Reddit',
description: 'Fetch popular posts from Reddit',
description: 'Access Reddit data and content',
longDescription:
'Access Reddit data to retrieve the most popular (hot) posts from any subreddit. Get post titles, content, authors, scores, and more.',
'Access Reddit data to retrieve posts and comments from any subreddit. Get post titles, content, authors, scores, comments and more.',
category: 'tools',
bgColor: '#FF5700',
icon: RedditIcon,
subBlocks: [
// Subreddit input
// Action selection
{
id: 'action',
title: 'Action',
type: 'dropdown',
layout: 'full',
options: [
{ label: 'Get Posts', id: 'get_posts' },
{ label: 'Get Comments', id: 'get_comments' }
],
},
// Common fields - appear for all actions
{
id: 'subreddit',
title: 'Subreddit',
type: 'short-input',
layout: 'full',
placeholder: 'Enter subreddit name (without r/)',
condition: {
field: 'action',
value: ['get_posts', 'get_comments']
}
},
// Get Posts specific fields
{
id: 'sort',
title: 'Sort By',
type: 'dropdown',
layout: 'full',
options: [
{ label: 'Hot', id: 'hot' },
{ label: 'New', id: 'new' },
{ label: 'Top', id: 'top' },
{ label: 'Rising', id: 'rising' }
],
condition: {
field: 'action',
value: 'get_posts'
}
},
{
id: 'time',
title: 'Time Filter (for Top sort)',
type: 'dropdown',
layout: 'full',
options: [
{ label: 'Day', id: 'day' },
{ label: 'Week', id: 'week' },
{ label: 'Month', id: 'month' },
{ label: 'Year', id: 'year' },
{ label: 'All Time', id: 'all' }
],
condition: {
field: 'action',
value: 'get_posts',
and: {
field: 'sort',
value: 'top'
}
}
},
// Limit input
{
id: 'limit',
title: 'Number of Top Posts',
title: 'Number of Posts',
type: 'short-input',
layout: 'full',
placeholder: '10',
condition: {
field: 'action',
value: 'get_posts'
}
},
// Get Comments specific fields
{
id: 'postId',
title: 'Post ID',
type: 'short-input',
layout: 'full',
placeholder: 'Enter post ID',
condition: {
field: 'action',
value: 'get_comments'
}
},
{
id: 'commentSort',
title: 'Sort Comments By',
type: 'dropdown',
layout: 'full',
options: [
{ label: 'Confidence', id: 'confidence' },
{ label: 'Top', id: 'top' },
{ label: 'New', id: 'new' },
{ label: 'Controversial', id: 'controversial' },
{ label: 'Old', id: 'old' },
{ label: 'Random', id: 'random' },
{ label: 'Q&A', id: 'qa' }
],
condition: {
field: 'action',
value: 'get_comments'
}
},
{
id: 'commentLimit',
title: 'Number of Comments',
type: 'short-input',
layout: 'full',
placeholder: '50',
condition: {
field: 'action',
value: 'get_comments'
}
}
],
tools: {
access: ['reddit_hot_posts'],
access: ['reddit_hot_posts', 'reddit_get_posts', 'reddit_get_comments'],
config: {
tool: () => 'reddit_hot_posts',
},
tool: (inputs) => {
const action = inputs.action || 'get_posts'
if (action === 'get_comments') {
return 'reddit_get_comments'
}
return 'reddit_get_posts'
},
params: (inputs) => {
const action = inputs.action || 'get_posts'
if (action === 'get_comments') {
return {
postId: inputs.postId,
subreddit: inputs.subreddit,
sort: inputs.commentSort,
limit: inputs.commentLimit ? parseInt(inputs.commentLimit) : undefined
}
}
return {
subreddit: inputs.subreddit,
sort: inputs.sort,
limit: inputs.limit ? parseInt(inputs.limit) : undefined,
time: inputs.sort === 'top' ? inputs.time : undefined
}
}
}
},
inputs: {
action: {
type: 'string',
required: true,
description: 'The action to perform: get_posts or get_comments',
},
subreddit: {
type: 'string',
required: true,
description: 'The name of the subreddit to fetch posts from (without the r/ prefix)',
description: 'The name of the subreddit to fetch data from (without the r/ prefix)',
},
sort: {
type: 'string',
required: true,
description: 'Sort method for posts: "hot", "new", "top", or "rising" (default: "hot")',
},
time: {
type: 'string',
required: false,
description: 'Time filter for "top" sorted posts: "hour", "day", "week", "month", "year", or "all" (default: "day")',
},
limit: {
type: 'number',
required: false,
description: 'Maximum number of posts to return (default: 10, max: 100)',
},
postId: {
type: 'string',
required: true,
description: 'The ID of the Reddit post to fetch comments from',
},
commentSort: {
type: 'string',
required: false,
description: 'Sort method for comments: "confidence", "top", "new", "controversial", "old", "random", "qa" (default: "confidence")',
},
commentLimit: {
type: 'number',
required: false,
description: 'Maximum number of comments to return (default: 50, max: 100)',
}
},
outputs: {
response: {
type: {
subreddit: 'string',
posts: 'json',
post: 'json',
comments: 'json'
},
},
},
+110
View File
@@ -0,0 +1,110 @@
import fetch from 'node-fetch'
import { ToolConfig } from '../types'
import { RedditCommentsParams, RedditCommentsResponse } from './types'
export const getCommentsTool: ToolConfig<RedditCommentsParams, RedditCommentsResponse> = {
id: 'reddit_get_comments',
name: 'Get Reddit Comments',
description: 'Fetch comments from a specific Reddit post',
version: '1.0.0',
params: {
postId: {
type: 'string',
required: true,
description: 'The ID of the Reddit post to fetch comments from'
},
subreddit: {
type: 'string',
required: true,
description: 'The subreddit where the post is located (without the r/ prefix)'
},
sort: {
type: 'string',
required: false,
description: 'Sort method for comments: "confidence", "top", "new", "controversial", "old", "random", "qa" (default: "confidence")'
},
limit: {
type: 'number',
required: false,
description: 'Maximum number of comments to return (default: 50, max: 100)'
}
},
request: {
url: (params: RedditCommentsParams) => {
// Sanitize inputs
const subreddit = params.subreddit.trim().replace(/^r\//, '')
const sort = params.sort || 'confidence'
const limit = Math.min(Math.max(1, params.limit || 50), 100)
// Build URL
return `https://www.reddit.com/r/${subreddit}/comments/${params.postId}.json?sort=${sort}&limit=${limit}`
},
method: 'GET',
headers: () => ({
'User-Agent': 'Sim Studio Reddit Tool/1.0'
})
},
transformResponse: async (response: Response) => {
const data = await response.json()
// Extract post data (first element in the array)
const postData = data[0]?.data?.children[0]?.data || {}
// Extract and transform comments (second element in the array)
const commentsData = data[1]?.data?.children || []
// Recursive function to process nested comments
const processComments = (comments: any[]): any[] => {
return comments.map(comment => {
const commentData = comment.data
// Skip non-comment items like "more" items
if (!commentData || comment.kind !== 't1') {
return null
}
// Process nested replies if they exist
const replies = commentData.replies &&
commentData.replies.data &&
commentData.replies.data.children ?
processComments(commentData.replies.data.children) :
[]
return {
id: commentData.id,
author: commentData.author,
body: commentData.body,
created_utc: commentData.created_utc,
score: commentData.score,
permalink: `https://www.reddit.com${commentData.permalink}`,
replies: replies.filter(Boolean)
}
}).filter(Boolean)
}
const comments = processComments(commentsData)
return {
success: true,
output: {
post: {
id: postData.id,
title: postData.title,
author: postData.author,
selftext: postData.selftext,
created_utc: postData.created_utc,
score: postData.score,
permalink: `https://www.reddit.com${postData.permalink}`
},
comments: comments
}
}
},
transformError: (error) => {
return `Error fetching Reddit comments: ${error.message}`
}
}
+94
View File
@@ -0,0 +1,94 @@
import fetch from 'node-fetch'
import { ToolConfig } from '../types'
import { RedditPostsParams, RedditPostsResponse } from './types'
export const getPostsTool: ToolConfig<RedditPostsParams, RedditPostsResponse> = {
id: 'reddit_get_posts',
name: 'Get Reddit Posts',
description: 'Fetch posts from a subreddit with different sorting options',
version: '1.0.0',
params: {
subreddit: {
type: 'string',
required: true,
description: 'The name of the subreddit to fetch posts from (without the r/ prefix)'
},
sort: {
type: 'string',
required: false,
description: 'Sort method for posts: "hot", "new", "top", or "rising" (default: "hot")'
},
limit: {
type: 'number',
required: false,
description: 'Maximum number of posts to return (default: 10, max: 100)'
},
time: {
type: 'string',
required: false,
description: 'Time filter for "top" sorted posts: "day", "week", "month", "year", or "all" (default: "day")'
}
},
request: {
url: (params: RedditPostsParams) => {
// Sanitize inputs
const subreddit = params.subreddit.trim().replace(/^r\//, '')
const sort = params.sort || 'hot'
const limit = Math.min(Math.max(1, params.limit || 10), 100)
// Build URL with appropriate parameters
let url = `https://www.reddit.com/r/${subreddit}/${sort}.json?limit=${limit}`
// Add time parameter only for 'top' sorting
if (sort === 'top' && params.time) {
url += `&t=${params.time}`
}
return url
},
method: 'GET',
headers: () => ({
'User-Agent': 'Sim Studio Reddit Tool/1.0'
})
},
transformResponse: async (response: Response) => {
const data = await response.json()
// Extract subreddit name from response
const subredditName = data.data?.children[0]?.data?.subreddit || 'unknown'
// Transform posts data
const posts = 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,
is_self: post.is_self,
selftext: post.selftext,
thumbnail: post.thumbnail,
subreddit: post.subreddit
}
}) || []
return {
success: true,
output: {
subreddit: subredditName,
posts
}
}
},
transformError: (error) => {
return `Error fetching Reddit posts: ${error.message}`
}
}
+4
View File
@@ -1,3 +1,7 @@
import { hotPostsTool } from './hot_posts'
import { getPostsTool } from './get_posts'
import { getCommentsTool } from './get_comments'
export const redditHotPostsTool = hotPostsTool
export const redditGetPostsTool = getPostsTool
export const redditGetCommentsTool = getCommentsTool
+50
View File
@@ -16,9 +16,59 @@ export interface RedditPost {
subreddit_name_prefixed: string
}
export interface RedditComment {
id: string
author: string
body: string
created_utc: number
score: number
permalink: string
replies: RedditComment[]
}
export interface RedditHotPostsResponse extends ToolResponse {
output: {
subreddit: string
posts: RedditPost[]
}
}
// Parameters for the generalized get_posts tool
export interface RedditPostsParams {
subreddit: string
sort?: 'hot' | 'new' | 'top' | 'rising'
limit?: number
time?: 'day' | 'week' | 'month' | 'year' | 'all'
}
// Response for the generalized get_posts tool
export interface RedditPostsResponse extends ToolResponse {
output: {
subreddit: string
posts: RedditPost[]
}
}
// Parameters for the get_comments tool
export interface RedditCommentsParams {
postId: string
subreddit: string
sort?: 'confidence' | 'top' | 'new' | 'controversial' | 'old' | 'random' | 'qa'
limit?: number
}
// Response for the get_comments tool
export interface RedditCommentsResponse extends ToolResponse {
output: {
post: {
id: string
title: string
author: string
selftext?: string
created_utc: number
score: number
permalink: string
}
comments: RedditComment[]
}
}
+3 -1
View File
@@ -22,7 +22,7 @@ import { notionReadTool, notionWriteTool } from './notion'
import { dalleTool, embeddingsTool as openAIEmbeddings } from './openai'
import { perplexityChatTool } from './perplexity'
import { pineconeFetchTool, pineconeGenerateEmbeddingsTool, pineconeSearchTextTool, pineconeSearchVectorTool, pineconeUpsertTextTool } from './pinecone'
import { redditHotPostsTool } from './reddit'
import { redditHotPostsTool, redditGetPostsTool, redditGetCommentsTool } from './reddit'
import { opportunitiesTool as salesforceOpportunities } from './salesforce/opportunities'
import { searchTool as serperSearch } from './serper'
import { sheetsReadTool, sheetsUpdateTool, sheetsWriteTool } from './google_sheets'
@@ -94,6 +94,8 @@ export const tools: Record<string, ToolConfig> = {
exa_find_similar_links: exaFindSimilarLinksTool,
exa_answer: exaAnswerTool,
reddit_hot_posts: redditHotPostsTool,
reddit_get_posts: redditGetPostsTool,
reddit_get_comments: redditGetCommentsTool,
google_drive_download: driveDownloadTool,
google_drive_list: driveListTool,
google_drive_upload: driveUploadTool,