mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
feat(tools): added additional reddit tools, docs
This commit is contained in:
@@ -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
@@ -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'
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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}`
|
||||
}
|
||||
}
|
||||
@@ -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}`
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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[]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user