mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-23 05:47:59 -05:00
117 lines
3.4 KiB
TypeScript
117 lines
3.4 KiB
TypeScript
import { ToolConfig } from '../types'
|
|
import { XTweet, XUser, XUserParams, XUserResponse } from './types'
|
|
|
|
export const userTool: ToolConfig<XUserParams, XUserResponse> = {
|
|
id: 'x_user',
|
|
name: 'X User',
|
|
description: 'Get user profile information and recent tweets',
|
|
version: '1.0.0',
|
|
|
|
params: {
|
|
apiKey: {
|
|
type: 'string',
|
|
required: true,
|
|
requiredForToolCall: true,
|
|
description: 'X API key for authentication',
|
|
},
|
|
username: {
|
|
type: 'string',
|
|
required: true,
|
|
description: 'Username to look up (without @ symbol)',
|
|
},
|
|
includeRecentTweets: {
|
|
type: 'boolean',
|
|
required: false,
|
|
description: 'Whether to include recent tweets from the user',
|
|
},
|
|
},
|
|
|
|
request: {
|
|
url: (params) => {
|
|
const username = encodeURIComponent(params.username)
|
|
const userFields = ['description', 'profile_image_url', 'verified', 'public_metrics'].join(
|
|
','
|
|
)
|
|
|
|
return `https://api.twitter.com/2/users/by/username/${username}?user.fields=${userFields}`
|
|
},
|
|
method: 'GET',
|
|
headers: (params) => ({
|
|
Authorization: `Bearer ${params.apiKey}`,
|
|
'Content-Type': 'application/json',
|
|
}),
|
|
},
|
|
|
|
transformResponse: async (response: Response) => {
|
|
const data = await response.json()
|
|
const requestUrl = new URL(response.url)
|
|
const apiKey = response.headers.get('Authorization')?.split(' ')[1] || ''
|
|
|
|
const transformUser = (user: any): XUser => ({
|
|
id: user.id,
|
|
username: user.username,
|
|
name: user.name,
|
|
description: user.description,
|
|
profileImageUrl: user.profile_image_url,
|
|
verified: user.verified,
|
|
metrics: {
|
|
followersCount: user.public_metrics.followers_count,
|
|
followingCount: user.public_metrics.following_count,
|
|
tweetCount: user.public_metrics.tweet_count,
|
|
},
|
|
})
|
|
|
|
const transformTweet = (tweet: any): XTweet => ({
|
|
id: tweet.id,
|
|
text: tweet.text,
|
|
createdAt: tweet.created_at,
|
|
authorId: tweet.author_id,
|
|
conversationId: tweet.conversation_id,
|
|
inReplyToUserId: tweet.in_reply_to_user_id,
|
|
attachments: {
|
|
mediaKeys: tweet.attachments?.media_keys,
|
|
pollId: tweet.attachments?.poll_ids?.[0],
|
|
},
|
|
})
|
|
|
|
const user = transformUser(data.data)
|
|
let recentTweets: XTweet[] | undefined
|
|
|
|
// Check if includeRecentTweets was in the original request
|
|
const includeRecentTweets = requestUrl.searchParams.get('include_tweets') === 'true'
|
|
|
|
// Fetch recent tweets if requested
|
|
if (includeRecentTweets && apiKey) {
|
|
const tweetsResponse = await fetch(
|
|
`https://api.twitter.com/2/users/${user.id}/tweets?max_results=10&tweet.fields=created_at,conversation_id,in_reply_to_user_id,attachments`,
|
|
{
|
|
headers: {
|
|
Authorization: `Bearer ${apiKey}`,
|
|
'Content-Type': 'application/json',
|
|
},
|
|
}
|
|
)
|
|
const tweetsData = await tweetsResponse.json()
|
|
recentTweets = tweetsData.data.map(transformTweet)
|
|
}
|
|
|
|
return {
|
|
success: true,
|
|
output: {
|
|
user,
|
|
recentTweets,
|
|
},
|
|
}
|
|
},
|
|
|
|
transformError: (error) => {
|
|
if (error.title === 'Unauthorized') {
|
|
return 'Invalid API key. Please check your credentials.'
|
|
}
|
|
if (error.title === 'Not Found') {
|
|
return 'The specified user was not found.'
|
|
}
|
|
return error.detail || 'An unexpected error occurred while fetching user data from X'
|
|
},
|
|
}
|