From cdcbd6eaebf173f83a5888eedd2cb421eb9bb9b3 Mon Sep 17 00:00:00 2001 From: alexchvod Date: Sun, 26 Oct 2025 22:34:06 +0000 Subject: [PATCH 1/2] Refactor tools management by centralizing tool configurations and enhancing prompt generation. Introduced dynamic tool provider setup and improved tools categorization for better organization and accessibility. --- frontend/src/app/settings/page.tsx | 102 +------- frontend/src/lib/system-prompt.ts | 11 +- frontend/src/lib/tools-config.ts | 278 +++++++++++++++++++++ frontend/src/lib/tools-prompt-generator.ts | 43 ++++ frontend/src/lib/tools-providers.ts | 108 ++++++++ frontend/src/lib/tools-utils.ts | 32 +++ frontend/src/types/tools.ts | 31 +++ 7 files changed, 498 insertions(+), 107 deletions(-) create mode 100644 frontend/src/lib/tools-config.ts create mode 100644 frontend/src/lib/tools-prompt-generator.ts create mode 100644 frontend/src/lib/tools-providers.ts create mode 100644 frontend/src/lib/tools-utils.ts create mode 100644 frontend/src/types/tools.ts diff --git a/frontend/src/app/settings/page.tsx b/frontend/src/app/settings/page.tsx index d94c0f9..9a448ba 100644 --- a/frontend/src/app/settings/page.tsx +++ b/frontend/src/app/settings/page.tsx @@ -9,15 +9,9 @@ import { doc, updateDoc, serverTimestamp } from "firebase/firestore"; import { firestore } from "../../lib/firebase"; import { toast } from "sonner"; import { Footer } from "../../components/Footer"; -import { - GoogleIcon, - GitHubIcon, - NotionIcon, - SlackIcon, - XIcon, - SpotifyIcon, -} from "../../components/ProviderIcons"; import { Skeleton } from "../../components/ui/skeleton"; +import { ToolProvider } from "../../types/tools"; +import { toolsProviders } from "../../lib/tools-providers"; interface UserData { firstName: string; @@ -48,96 +42,8 @@ export default function SettingsPage() { const [checkingStatus, setCheckingStatus] = useState(true); const router = useRouter(); - // Available Arcade tools - const availableTools = [ - { - id: "google", - name: "Google", - description: "Access Gmail and Google services", - icon: GoogleIcon, - scopes: [ - "https://www.googleapis.com/auth/gmail.readonly", - "https://www.googleapis.com/auth/userinfo.profile", - "https://www.googleapis.com/auth/userinfo.email", - "https://www.googleapis.com/auth/gmail.send", - "https://www.googleapis.com/auth/gmail.modify", - ], - enabled: true, - }, - { - id: "github", - name: "GitHub", - description: "Access repositories and code", - icon: GitHubIcon, - scopes: ["repo"], - enabled: true, - }, - { - id: "notion", - name: "Notion", - description: "Connect your Notion workspace", - icon: NotionIcon, - enabled: true, - }, - { - id: "slack", - name: "Slack", - description: "Integrate with Slack channels", - icon: SlackIcon, - scopes: [ - "channels.read", - "channels.write", - "groups.read", - "groups:history", - "groups:write", - "im:history", - "im:read", - "im:write", - "mpim:history", - "mpim:read", - "mpim:write", - "users:read", - "users:read.email", - ], - enabled: true, - }, - { - id: "x", - name: "X", - description: "Integrate with X (Twitter)", - icon: XIcon, - scopes: ["tweet.read", "tweet.write"], - enabled: true, - }, - { - id: "spotify", - name: "Spotify", - description: "Integrate with Spotify", - icon: SpotifyIcon, - scopes: [ - "ugc-image-upload", - "user-follow-modify", - "playlist-modify-private", - "playlist-modify-public", - "user-library-modify", - "playlist-read-collaborative", - "user-read-currently-playing", - "user-follow-read", - "user-read-playback-position", - "user-read-playback-state", - "playlist-read-private", - "user-read-recently-played", - "user-top-read", - "user-read-email", - "user-library-read", - "user-read-private", - "app-remote-control", - "streaming", - "user-modify-playback-state", - ], - enabled: true, - }, - ]; + // Available Arcade tools - dynamically configured + const availableTools: ToolProvider[] = toolsProviders; useEffect(() => { if (!user) { diff --git a/frontend/src/lib/system-prompt.ts b/frontend/src/lib/system-prompt.ts index 7007229..730480a 100644 --- a/frontend/src/lib/system-prompt.ts +++ b/frontend/src/lib/system-prompt.ts @@ -1,14 +1,7 @@ -import fs from "fs"; -import path from "path"; - -// Read the tools prompt from Prompt.md -function getToolsPrompt(): string { - const promptPath = path.join(process.cwd(), "Prompt.md"); - return fs.readFileSync(promptPath, "utf-8"); -} +import { generateToolsPrompt } from './tools-prompt-generator'; export function getSystemPrompt(): string { - const tools_prompt = getToolsPrompt(); + const tools_prompt = generateToolsPrompt(); return `You are Workflow Builder. Your single goal is to iteratively build a valid WorkflowConfig. diff --git a/frontend/src/lib/tools-config.ts b/frontend/src/lib/tools-config.ts new file mode 100644 index 0000000..d333c81 --- /dev/null +++ b/frontend/src/lib/tools-config.ts @@ -0,0 +1,278 @@ +import { ToolsConfig, ToolDefinition, ToolParameter, ToolProvider } from '../types/tools'; + +// Twitter/X Tools +const twitterTools: ToolDefinition[] = [ + { + tool_name: "X.PostTweet", + description: "Post a tweet to X (Twitter).", + parameters: [ + { name: "tweet_text", type: "string", required: true, description: "The text content of the tweet you want to post" }, + { name: "quote_tweet_id", type: "string", required: false, description: "The ID of the tweet you want to quote. Optional." } + ], + category: "social" + } +]; + +// LinkedIn Tools +const linkedinTools: ToolDefinition[] = [ + { + tool_name: "LinkedIn.CreateTextPost", + description: "Share a new text post to LinkedIn.", + parameters: [ + { name: "text", type: "string", required: true, description: "The text content of the post." } + ], + category: "social" + } +]; + +// Google Search Tools +const googleSearchTools: ToolDefinition[] = [ + { + tool_name: "GoogleSearch.Search", + description: "Search Google using SerpAPI and return organic search results.", + parameters: [ + { name: "query", type: "string", required: true, description: "The search query." }, + { name: "n_results", type: "integer", required: false, description: "Number of results to retrieve.", default: 5 } + ], + category: "search" + } +]; + +// Slack Tools +const slackTools: ToolDefinition[] = [ + { + tool_name: "Slack.WhoAmI", + description: "Get comprehensive user profile information.", + parameters: [], + category: "communication" + }, + { + tool_name: "Slack.GetUsersInfo", + description: "Get the information of one or more users in Slack by ID, username, and/or email.", + parameters: [ + { name: "user_ids", type: "array[string]", required: false, description: "The IDs of the users to get" }, + { name: "usernames", type: "array[string]", required: false, description: "The usernames of the users to get. Prefer retrieving by user_ids and/or emails, when available, since the performance is better." }, + { name: "emails", type: "array[string]", required: false, description: "The emails of the users to get" } + ], + category: "communication" + }, + { + tool_name: "Slack.ListUsers", + description: "List all users in the authenticated user's Slack team.", + parameters: [ + { name: "exclude_bots", type: "boolean", required: false, description: "Whether to exclude bots from the results.", default: true }, + { name: "limit", type: "integer", required: false, description: "The maximum number of users to return.", default: 200 }, + { name: "next_cursor", type: "string", required: false, description: "The next cursor token to use for pagination." } + ], + category: "communication" + }, + { + tool_name: "Slack.SendMessage", + description: "Send a message to a Channel, Direct Message (IM/DM), or Multi-Person (MPIM) conversation.", + parameters: [ + { name: "message", type: "string", required: true, description: "The content of the message to send." }, + { name: "channel_name", type: "string", required: false, description: "The channel name to send the message to. Prefer providing a conversation_id, when available, since the performance is better." }, + { name: "conversation_id", type: "string", required: false, description: "The conversation ID to send the message to." }, + { name: "user_ids", type: "array[string]", required: false, description: "The Slack user IDs of the people to message." }, + { name: "emails", type: "array[string]", required: false, description: "The emails of the people to message." }, + { name: "usernames", type: "array[string]", required: false, description: "The Slack usernames of the people to message. Prefer providing user_ids and/or emails, when available, since the performance is better." } + ], + category: "communication" + } +]; + +// Google Calendar Tools +const googleCalendarTools: ToolDefinition[] = [ + { + tool_name: "GoogleCalendar.ListCalendars", + description: "List all calendars accessible by the user.", + parameters: [ + { name: "max_results", type: "integer", required: false, description: "The maximum number of calendars to return. Up to 250 calendars", default: 10 }, + { name: "show_deleted", type: "boolean", required: false, description: "Whether to show deleted calendars.", default: false }, + { name: "show_hidden", type: "boolean", required: false, description: "Whether to show hidden calendars.", default: false }, + { name: "next_page_token", type: "string", required: false, description: "The token to retrieve the next page of calendars. Optional." } + ], + category: "calendar" + }, + { + tool_name: "GoogleCalendar.CreateEvent", + description: "Create a new event/meeting/sync/meetup in the specified calendar.", + parameters: [ + { name: "summary", type: "string", required: true, description: "The title of the event" }, + { name: "start_datetime", type: "string", required: true, description: "The datetime when the event starts in ISO 8601 format, e.g., '2024-12-31T15:30:00'." }, + { name: "end_datetime", type: "string", required: true, description: "The datetime when the event ends in ISO 8601 format, e.g., '2024-12-31T17:30:00'." }, + { name: "calendar_id", type: "string", required: false, description: "The ID of the calendar to create the event in, usually 'primary'." }, + { name: "description", type: "string", required: false, description: "The description of the event" }, + { name: "location", type: "string", required: false, description: "The location of the event" }, + { name: "visibility", type: "Enum", required: false, description: "The visibility of the event" }, + { name: "attendee_emails", type: "array[string]", required: false, description: "The list of attendee emails. Must be valid email addresses e.g., username@domain.com." }, + { name: "send_notifications_to_attendees", type: "Enum", required: false, description: "Should attendees be notified by email of the invitation? (none, all, external_only)" }, + { name: "add_google_meet", type: "boolean", required: false, description: "Whether to add a Google Meet link to the event.", default: false } + ], + category: "calendar" + } +]; + +// Google Finance Tools +const googleFinanceTools: ToolDefinition[] = [ + { + tool_name: "GoogleFinance.GetStockSummary", + description: "Retrieve summary information for a given stock using the Google Finance API via SerpAPI. This tool returns the current price and price change from the most recent trading day.", + parameters: [ + { name: "ticker_symbol", type: "string", required: true, description: "The stock ticker, e.g., 'GOOG'." }, + { name: "exchange_identifier", type: "string", required: true, description: "The market identifier, e.g., 'NASDAQ'." } + ], + category: "finance" + } +]; + +// Gmail Tools +const gmailTools: ToolDefinition[] = [ + { + tool_name: "Gmail.SendEmail", + description: "Send an email using the Gmail API.", + parameters: [ + { name: "subject", type: "string", required: true, description: "The subject of the email." }, + { name: "body", type: "string", required: true, description: "The body of the email." }, + { name: "recipient", type: "string", required: true, description: "The recipient of the email." }, + { name: "cc", type: "array", required: false, description: "CC recipients of the email." }, + { name: "bcc", type: "array", required: false, description: "BCC recipients of the email." } + ], + category: "email" + }, + { + tool_name: "Gmail.SendDraftEmail", + description: "Send a draft email using the Gmail API.", + parameters: [ + { name: "email_id", type: "string", required: true, description: "The ID of the draft to send." } + ], + category: "email" + }, + { + tool_name: "Gmail.WriteDraftEmail", + description: "Compose a new email draft using the Gmail API.", + parameters: [ + { name: "subject", type: "string", required: true, description: "The subject of the draft email." }, + { name: "body", type: "string", required: true, description: "The body of the draft email." }, + { name: "recipient", type: "string", required: true, description: "The recipient of the draft email." }, + { name: "cc", type: "array", required: false, description: "CC recipients of the draft email." }, + { name: "bcc", type: "array", required: false, description: "BCC recipients of the draft email." } + ], + category: "email" + } +]; + +// GitHub Tools +const githubTools: ToolDefinition[] = [ + { + tool_name: "GitHub.GetUser", + description: "Get information about the authenticated GitHub user.", + parameters: [], + category: "development" + }, + { + tool_name: "GitHub.ListRepositories", + description: "List repositories accessible to the authenticated user.", + parameters: [ + { name: "visibility", type: "string", required: false, description: "Filter by repository visibility. Options: 'all', 'public', 'private'.", default: "all" }, + { name: "sort", type: "string", required: false, description: "Sort repositories by. Options: 'created', 'updated', 'pushed', 'full_name'.", default: "full_name" }, + { name: "per_page", type: "integer", required: false, description: "Number of repositories per page.", default: 30 }, + { name: "page", type: "integer", required: false, description: "Page number for pagination.", default: 1 } + ], + category: "development" + }, + { + tool_name: "GitHub.CreatePullRequest", + description: "Create a new pull request in a repository.", + parameters: [ + { name: "owner", type: "string", required: true, description: "The repository owner's username." }, + { name: "repo", type: "string", required: true, description: "The repository name." }, + { name: "title", type: "string", required: true, description: "The title of the pull request." }, + { name: "body", type: "string", required: false, description: "The description of the pull request." }, + { name: "head", type: "string", required: true, description: "The name of the branch where your changes are implemented." }, + { name: "base", type: "string", required: true, description: "The name of the branch you want the changes pulled into." } + ], + category: "development" + } +]; + +// Notion Tools +const notionTools: ToolDefinition[] = [ + { + tool_name: "Notion.SearchPages", + description: "Search for pages in Notion.", + parameters: [ + { name: "query", type: "string", required: false, description: "The text to search for." }, + { name: "filter", type: "object", required: false, description: "Filter results by type. Options: { \"property\": \"object\", \"value\": \"page\" } or { \"property\": \"object\", \"value\": \"database\" }." }, + { name: "sort", type: "object", required: false, description: "Sort the results. Example: { \"direction\": \"ascending\", \"timestamp\": \"last_edited_time\" }." }, + { name: "page_size", type: "integer", required: false, description: "Number of results per page.", default: 100 }, + { name: "start_cursor", type: "string", required: false, description: "Pagination cursor." } + ], + category: "productivity" + }, + { + tool_name: "Notion.CreatePage", + description: "Create a new page in Notion.", + parameters: [ + { name: "parent_id", type: "string", required: true, description: "The ID of the parent page or database." }, + { name: "parent_type", type: "string", required: true, description: "Type of parent. Options: 'page_id', 'database_id'." }, + { name: "title", type: "string", required: true, description: "The title of the new page." }, + { name: "content", type: "array[object]", required: false, description: "The content blocks for the page." }, + { name: "properties", type: "object", required: false, description: "Properties for the page (required if parent is a database)." } + ], + category: "productivity" + } +]; + +// Spotify Tools +const spotifyTools: ToolDefinition[] = [ + { + tool_name: "Spotify.GetTrackFromId", + description: "Get information about a track.", + parameters: [ + { name: "track_id", type: "string", required: true, description: "The Spotify ID of the track." } + ], + category: "music" + }, + { + tool_name: "Spotify.PlayTrackByName", + description: "Plays a song by name. Note: This tool currently requires a self-hosted instance of Arcade.", + parameters: [ + { name: "track_name", type: "string", required: true, description: "The name of the track to play." }, + { name: "artist_name", type: "string", required: false, description: "The name of the artist of the track." } + ], + category: "music" + }, + { + tool_name: "Spotify.Search", + description: "Search Spotify catalog information. Note: This tool currently requires a self-hosted instance of Arcade.", + parameters: [ + { name: "q", type: "string", required: true, description: "The search query." }, + { name: "types", type: "array", required: true, description: "The types of results to return, Valid values are 'album', 'artist', 'playlist', 'track', 'show', 'episode', 'audiobook'." }, + { name: "limit", type: "integer", required: false, description: "The maximum number of results to return.", default: 1 } + ], + category: "music" + } +]; + +// Combine all tools +const allTools: ToolDefinition[] = [ + ...twitterTools, + ...linkedinTools, + ...googleSearchTools, + ...slackTools, + ...googleCalendarTools, + ...googleFinanceTools, + ...gmailTools, + ...githubTools, + ...notionTools, + ...spotifyTools +]; + +export const toolsConfig: ToolsConfig = { + providers: [], + tools: allTools +}; + +export type { ToolParameter, ToolDefinition, ToolProvider, ToolsConfig }; +export default toolsConfig; diff --git a/frontend/src/lib/tools-prompt-generator.ts b/frontend/src/lib/tools-prompt-generator.ts new file mode 100644 index 0000000..ea14f9a --- /dev/null +++ b/frontend/src/lib/tools-prompt-generator.ts @@ -0,0 +1,43 @@ +import { toolsConfig, ToolParameter } from './tools-config'; + +export function generateToolsPrompt(): string { + let prompt = "# TIMEZONE\n\n- We are in the timezone: New York\n- Time now: {time}\n\n"; + + // Group tools by category/provider + const toolsByCategory: { [key: string]: any[] } = {}; + + toolsConfig.tools.forEach(tool => { + const category = tool.category || 'other'; + if (!toolsByCategory[category]) { + toolsByCategory[category] = []; + } + toolsByCategory[category].push(tool); + }); + + // Generate sections for each category + Object.entries(toolsByCategory).forEach(([category, tools]) => { + const categoryTitle = category.charAt(0).toUpperCase() + category.slice(1); + prompt += `## ${categoryTitle}\n\n`; + + tools.forEach(tool => { + prompt += `tool_name = "${tool.tool_name}"\n`; + prompt += `${tool.description}\n\n`; + + if (tool.parameters && tool.parameters.length > 0) { + prompt += "Parameters:\n\n"; + tool.parameters.forEach((param: ToolParameter) => { + const required = param.required ? "required" : "optional"; + const defaultValue = param.default ? `, Defaults to ${param.default}` : ""; + prompt += `- ${param.name} (${param.type}, ${required}${defaultValue}) ${param.description || ''}\n`; + }); + } else { + prompt += "Parameters:\nThis tool takes no parameters.\n"; + } + prompt += "\n"; + }); + }); + + return prompt; +} + +export default generateToolsPrompt; diff --git a/frontend/src/lib/tools-providers.ts b/frontend/src/lib/tools-providers.ts new file mode 100644 index 0000000..e32f69a --- /dev/null +++ b/frontend/src/lib/tools-providers.ts @@ -0,0 +1,108 @@ +import { ToolProvider } from '../types/tools'; +import { + GoogleIcon, + GitHubIcon, + NotionIcon, + SlackIcon, + XIcon, + SpotifyIcon, +} from '../components/ProviderIcons'; + +// Centralized tools configuration for providers +export const toolsProviders: ToolProvider[] = [ + { + id: "google", + name: "Google", + description: "Access Gmail and Google services", + icon: GoogleIcon, + scopes: [ + "https://www.googleapis.com/auth/gmail.readonly", + "https://www.googleapis.com/auth/userinfo.profile", + "https://www.googleapis.com/auth/userinfo.email", + "https://www.googleapis.com/auth/gmail.send", + "https://www.googleapis.com/auth/gmail.modify", + ], + enabled: true, + tools: [], + }, + { + id: "github", + name: "GitHub", + description: "Access repositories and code", + icon: GitHubIcon, + scopes: ["repo"], + enabled: true, + tools: [], + }, + { + id: "notion", + name: "Notion", + description: "Connect your Notion workspace", + icon: NotionIcon, + enabled: true, + tools: [], + }, + { + id: "slack", + name: "Slack", + description: "Integrate with Slack channels", + icon: SlackIcon, + scopes: [ + "channels.read", + "channels.write", + "groups.read", + "groups:history", + "groups:write", + "im:history", + "im:read", + "im:write", + "mpim:history", + "mpim:read", + "mpim:write", + "users:read", + "users:read.email", + ], + enabled: true, + tools: [], + }, + { + id: "x", + name: "X", + description: "Integrate with X (Twitter)", + icon: XIcon, + scopes: ["tweet.read", "tweet.write"], + enabled: true, + tools: [], + }, + { + id: "spotify", + name: "Spotify", + description: "Integrate with Spotify", + icon: SpotifyIcon, + scopes: [ + "ugc-image-upload", + "user-follow-modify", + "playlist-modify-private", + "playlist-modify-public", + "user-library-modify", + "playlist-read-collaborative", + "user-read-currently-playing", + "user-follow-read", + "user-read-playback-position", + "user-read-playback-state", + "playlist-read-private", + "user-read-recently-played", + "user-top-read", + "user-read-email", + "user-library-read", + "user-read-private", + "app-remote-control", + "streaming", + "user-modify-playback-state", + ], + enabled: true, + tools: [], + }, +]; + +export default toolsProviders; diff --git a/frontend/src/lib/tools-utils.ts b/frontend/src/lib/tools-utils.ts new file mode 100644 index 0000000..59144df --- /dev/null +++ b/frontend/src/lib/tools-utils.ts @@ -0,0 +1,32 @@ +import { toolsConfig } from './tools-config'; + +// Export tools list for backend consumption (e.g., coral_factory) +export function getAvailableTools(): string[] { + return toolsConfig.tools.map(tool => tool.tool_name); +} + +// Export tools by category for better organization +export function getToolsByCategory(): { [category: string]: string[] } { + const toolsByCategory: { [category: string]: string[] } = {}; + + toolsConfig.tools.forEach(tool => { + const category = tool.category || 'other'; + if (!toolsByCategory[category]) { + toolsByCategory[category] = []; + } + toolsByCategory[category].push(tool.tool_name); + }); + + return toolsByCategory; +} + +// Export individual tool definitions for detailed information +export function getToolDefinition(toolName: string) { + return toolsConfig.tools.find(tool => tool.tool_name === toolName); +} + +export default { + getAvailableTools, + getToolsByCategory, + getToolDefinition, +}; diff --git a/frontend/src/types/tools.ts b/frontend/src/types/tools.ts new file mode 100644 index 0000000..f63d31b --- /dev/null +++ b/frontend/src/types/tools.ts @@ -0,0 +1,31 @@ +export interface ToolParameter { + name: string; + type: string; + required: boolean; + description?: string; + optional?: boolean; + default?: any; +} + +export interface ToolDefinition { + tool_name: string; + description: string; + parameters: ToolParameter[]; + category?: string; + enabled?: boolean; +} + +export interface ToolProvider { + id: string; + name: string; + description: string; + icon: React.ComponentType; + scopes?: string[]; + enabled: boolean; + tools: ToolDefinition[]; +} + +export interface ToolsConfig { + providers: ToolProvider[]; + tools: ToolDefinition[]; +} From a52ce12acfa928046a1ac8b35a55412b2cf0600f Mon Sep 17 00:00:00 2001 From: Alex Choi Date: Mon, 27 Oct 2025 09:32:18 +0000 Subject: [PATCH 2/2] format --- frontend/src/lib/system-prompt.ts | 2 +- frontend/src/lib/tools-config.ts | 614 +++++++++++++++++---- frontend/src/lib/tools-prompt-generator.ts | 23 +- frontend/src/lib/tools-providers.ts | 4 +- frontend/src/lib/tools-utils.ts | 14 +- 5 files changed, 526 insertions(+), 131 deletions(-) diff --git a/frontend/src/lib/system-prompt.ts b/frontend/src/lib/system-prompt.ts index 730480a..1c72565 100644 --- a/frontend/src/lib/system-prompt.ts +++ b/frontend/src/lib/system-prompt.ts @@ -1,4 +1,4 @@ -import { generateToolsPrompt } from './tools-prompt-generator'; +import { generateToolsPrompt } from "./tools-prompt-generator"; export function getSystemPrompt(): string { const tools_prompt = generateToolsPrompt(); diff --git a/frontend/src/lib/tools-config.ts b/frontend/src/lib/tools-config.ts index d333c81..86c0409 100644 --- a/frontend/src/lib/tools-config.ts +++ b/frontend/src/lib/tools-config.ts @@ -1,4 +1,9 @@ -import { ToolsConfig, ToolDefinition, ToolParameter, ToolProvider } from '../types/tools'; +import { + ToolsConfig, + ToolDefinition, + ToolParameter, + ToolProvider, +} from "../types/tools"; // Twitter/X Tools const twitterTools: ToolDefinition[] = [ @@ -6,11 +11,21 @@ const twitterTools: ToolDefinition[] = [ tool_name: "X.PostTweet", description: "Post a tweet to X (Twitter).", parameters: [ - { name: "tweet_text", type: "string", required: true, description: "The text content of the tweet you want to post" }, - { name: "quote_tweet_id", type: "string", required: false, description: "The ID of the tweet you want to quote. Optional." } + { + name: "tweet_text", + type: "string", + required: true, + description: "The text content of the tweet you want to post", + }, + { + name: "quote_tweet_id", + type: "string", + required: false, + description: "The ID of the tweet you want to quote. Optional.", + }, ], - category: "social" - } + category: "social", + }, ]; // LinkedIn Tools @@ -19,23 +34,40 @@ const linkedinTools: ToolDefinition[] = [ tool_name: "LinkedIn.CreateTextPost", description: "Share a new text post to LinkedIn.", parameters: [ - { name: "text", type: "string", required: true, description: "The text content of the post." } + { + name: "text", + type: "string", + required: true, + description: "The text content of the post.", + }, ], - category: "social" - } + category: "social", + }, ]; // Google Search Tools const googleSearchTools: ToolDefinition[] = [ { tool_name: "GoogleSearch.Search", - description: "Search Google using SerpAPI and return organic search results.", + description: + "Search Google using SerpAPI and return organic search results.", parameters: [ - { name: "query", type: "string", required: true, description: "The search query." }, - { name: "n_results", type: "integer", required: false, description: "Number of results to retrieve.", default: 5 } + { + name: "query", + type: "string", + required: true, + description: "The search query.", + }, + { + name: "n_results", + type: "integer", + required: false, + description: "Number of results to retrieve.", + default: 5, + }, ], - category: "search" - } + category: "search", + }, ]; // Slack Tools @@ -44,41 +76,108 @@ const slackTools: ToolDefinition[] = [ tool_name: "Slack.WhoAmI", description: "Get comprehensive user profile information.", parameters: [], - category: "communication" + category: "communication", }, { tool_name: "Slack.GetUsersInfo", - description: "Get the information of one or more users in Slack by ID, username, and/or email.", + description: + "Get the information of one or more users in Slack by ID, username, and/or email.", parameters: [ - { name: "user_ids", type: "array[string]", required: false, description: "The IDs of the users to get" }, - { name: "usernames", type: "array[string]", required: false, description: "The usernames of the users to get. Prefer retrieving by user_ids and/or emails, when available, since the performance is better." }, - { name: "emails", type: "array[string]", required: false, description: "The emails of the users to get" } + { + name: "user_ids", + type: "array[string]", + required: false, + description: "The IDs of the users to get", + }, + { + name: "usernames", + type: "array[string]", + required: false, + description: + "The usernames of the users to get. Prefer retrieving by user_ids and/or emails, when available, since the performance is better.", + }, + { + name: "emails", + type: "array[string]", + required: false, + description: "The emails of the users to get", + }, ], - category: "communication" + category: "communication", }, { tool_name: "Slack.ListUsers", description: "List all users in the authenticated user's Slack team.", parameters: [ - { name: "exclude_bots", type: "boolean", required: false, description: "Whether to exclude bots from the results.", default: true }, - { name: "limit", type: "integer", required: false, description: "The maximum number of users to return.", default: 200 }, - { name: "next_cursor", type: "string", required: false, description: "The next cursor token to use for pagination." } + { + name: "exclude_bots", + type: "boolean", + required: false, + description: "Whether to exclude bots from the results.", + default: true, + }, + { + name: "limit", + type: "integer", + required: false, + description: "The maximum number of users to return.", + default: 200, + }, + { + name: "next_cursor", + type: "string", + required: false, + description: "The next cursor token to use for pagination.", + }, ], - category: "communication" + category: "communication", }, { tool_name: "Slack.SendMessage", - description: "Send a message to a Channel, Direct Message (IM/DM), or Multi-Person (MPIM) conversation.", + description: + "Send a message to a Channel, Direct Message (IM/DM), or Multi-Person (MPIM) conversation.", parameters: [ - { name: "message", type: "string", required: true, description: "The content of the message to send." }, - { name: "channel_name", type: "string", required: false, description: "The channel name to send the message to. Prefer providing a conversation_id, when available, since the performance is better." }, - { name: "conversation_id", type: "string", required: false, description: "The conversation ID to send the message to." }, - { name: "user_ids", type: "array[string]", required: false, description: "The Slack user IDs of the people to message." }, - { name: "emails", type: "array[string]", required: false, description: "The emails of the people to message." }, - { name: "usernames", type: "array[string]", required: false, description: "The Slack usernames of the people to message. Prefer providing user_ids and/or emails, when available, since the performance is better." } + { + name: "message", + type: "string", + required: true, + description: "The content of the message to send.", + }, + { + name: "channel_name", + type: "string", + required: false, + description: + "The channel name to send the message to. Prefer providing a conversation_id, when available, since the performance is better.", + }, + { + name: "conversation_id", + type: "string", + required: false, + description: "The conversation ID to send the message to.", + }, + { + name: "user_ids", + type: "array[string]", + required: false, + description: "The Slack user IDs of the people to message.", + }, + { + name: "emails", + type: "array[string]", + required: false, + description: "The emails of the people to message.", + }, + { + name: "usernames", + type: "array[string]", + required: false, + description: + "The Slack usernames of the people to message. Prefer providing user_ids and/or emails, when available, since the performance is better.", + }, ], - category: "communication" - } + category: "communication", + }, ]; // Google Calendar Tools @@ -87,43 +186,136 @@ const googleCalendarTools: ToolDefinition[] = [ tool_name: "GoogleCalendar.ListCalendars", description: "List all calendars accessible by the user.", parameters: [ - { name: "max_results", type: "integer", required: false, description: "The maximum number of calendars to return. Up to 250 calendars", default: 10 }, - { name: "show_deleted", type: "boolean", required: false, description: "Whether to show deleted calendars.", default: false }, - { name: "show_hidden", type: "boolean", required: false, description: "Whether to show hidden calendars.", default: false }, - { name: "next_page_token", type: "string", required: false, description: "The token to retrieve the next page of calendars. Optional." } + { + name: "max_results", + type: "integer", + required: false, + description: + "The maximum number of calendars to return. Up to 250 calendars", + default: 10, + }, + { + name: "show_deleted", + type: "boolean", + required: false, + description: "Whether to show deleted calendars.", + default: false, + }, + { + name: "show_hidden", + type: "boolean", + required: false, + description: "Whether to show hidden calendars.", + default: false, + }, + { + name: "next_page_token", + type: "string", + required: false, + description: + "The token to retrieve the next page of calendars. Optional.", + }, ], - category: "calendar" + category: "calendar", }, { tool_name: "GoogleCalendar.CreateEvent", - description: "Create a new event/meeting/sync/meetup in the specified calendar.", + description: + "Create a new event/meeting/sync/meetup in the specified calendar.", parameters: [ - { name: "summary", type: "string", required: true, description: "The title of the event" }, - { name: "start_datetime", type: "string", required: true, description: "The datetime when the event starts in ISO 8601 format, e.g., '2024-12-31T15:30:00'." }, - { name: "end_datetime", type: "string", required: true, description: "The datetime when the event ends in ISO 8601 format, e.g., '2024-12-31T17:30:00'." }, - { name: "calendar_id", type: "string", required: false, description: "The ID of the calendar to create the event in, usually 'primary'." }, - { name: "description", type: "string", required: false, description: "The description of the event" }, - { name: "location", type: "string", required: false, description: "The location of the event" }, - { name: "visibility", type: "Enum", required: false, description: "The visibility of the event" }, - { name: "attendee_emails", type: "array[string]", required: false, description: "The list of attendee emails. Must be valid email addresses e.g., username@domain.com." }, - { name: "send_notifications_to_attendees", type: "Enum", required: false, description: "Should attendees be notified by email of the invitation? (none, all, external_only)" }, - { name: "add_google_meet", type: "boolean", required: false, description: "Whether to add a Google Meet link to the event.", default: false } + { + name: "summary", + type: "string", + required: true, + description: "The title of the event", + }, + { + name: "start_datetime", + type: "string", + required: true, + description: + "The datetime when the event starts in ISO 8601 format, e.g., '2024-12-31T15:30:00'.", + }, + { + name: "end_datetime", + type: "string", + required: true, + description: + "The datetime when the event ends in ISO 8601 format, e.g., '2024-12-31T17:30:00'.", + }, + { + name: "calendar_id", + type: "string", + required: false, + description: + "The ID of the calendar to create the event in, usually 'primary'.", + }, + { + name: "description", + type: "string", + required: false, + description: "The description of the event", + }, + { + name: "location", + type: "string", + required: false, + description: "The location of the event", + }, + { + name: "visibility", + type: "Enum", + required: false, + description: "The visibility of the event", + }, + { + name: "attendee_emails", + type: "array[string]", + required: false, + description: + "The list of attendee emails. Must be valid email addresses e.g., username@domain.com.", + }, + { + name: "send_notifications_to_attendees", + type: "Enum", + required: false, + description: + "Should attendees be notified by email of the invitation? (none, all, external_only)", + }, + { + name: "add_google_meet", + type: "boolean", + required: false, + description: "Whether to add a Google Meet link to the event.", + default: false, + }, ], - category: "calendar" - } + category: "calendar", + }, ]; // Google Finance Tools const googleFinanceTools: ToolDefinition[] = [ { tool_name: "GoogleFinance.GetStockSummary", - description: "Retrieve summary information for a given stock using the Google Finance API via SerpAPI. This tool returns the current price and price change from the most recent trading day.", + description: + "Retrieve summary information for a given stock using the Google Finance API via SerpAPI. This tool returns the current price and price change from the most recent trading day.", parameters: [ - { name: "ticker_symbol", type: "string", required: true, description: "The stock ticker, e.g., 'GOOG'." }, - { name: "exchange_identifier", type: "string", required: true, description: "The market identifier, e.g., 'NASDAQ'." } + { + name: "ticker_symbol", + type: "string", + required: true, + description: "The stock ticker, e.g., 'GOOG'.", + }, + { + name: "exchange_identifier", + type: "string", + required: true, + description: "The market identifier, e.g., 'NASDAQ'.", + }, ], - category: "finance" - } + category: "finance", + }, ]; // Gmail Tools @@ -132,34 +324,89 @@ const gmailTools: ToolDefinition[] = [ tool_name: "Gmail.SendEmail", description: "Send an email using the Gmail API.", parameters: [ - { name: "subject", type: "string", required: true, description: "The subject of the email." }, - { name: "body", type: "string", required: true, description: "The body of the email." }, - { name: "recipient", type: "string", required: true, description: "The recipient of the email." }, - { name: "cc", type: "array", required: false, description: "CC recipients of the email." }, - { name: "bcc", type: "array", required: false, description: "BCC recipients of the email." } + { + name: "subject", + type: "string", + required: true, + description: "The subject of the email.", + }, + { + name: "body", + type: "string", + required: true, + description: "The body of the email.", + }, + { + name: "recipient", + type: "string", + required: true, + description: "The recipient of the email.", + }, + { + name: "cc", + type: "array", + required: false, + description: "CC recipients of the email.", + }, + { + name: "bcc", + type: "array", + required: false, + description: "BCC recipients of the email.", + }, ], - category: "email" + category: "email", }, { tool_name: "Gmail.SendDraftEmail", description: "Send a draft email using the Gmail API.", parameters: [ - { name: "email_id", type: "string", required: true, description: "The ID of the draft to send." } + { + name: "email_id", + type: "string", + required: true, + description: "The ID of the draft to send.", + }, ], - category: "email" + category: "email", }, { tool_name: "Gmail.WriteDraftEmail", description: "Compose a new email draft using the Gmail API.", parameters: [ - { name: "subject", type: "string", required: true, description: "The subject of the draft email." }, - { name: "body", type: "string", required: true, description: "The body of the draft email." }, - { name: "recipient", type: "string", required: true, description: "The recipient of the draft email." }, - { name: "cc", type: "array", required: false, description: "CC recipients of the draft email." }, - { name: "bcc", type: "array", required: false, description: "BCC recipients of the draft email." } + { + name: "subject", + type: "string", + required: true, + description: "The subject of the draft email.", + }, + { + name: "body", + type: "string", + required: true, + description: "The body of the draft email.", + }, + { + name: "recipient", + type: "string", + required: true, + description: "The recipient of the draft email.", + }, + { + name: "cc", + type: "array", + required: false, + description: "CC recipients of the draft email.", + }, + { + name: "bcc", + type: "array", + required: false, + description: "BCC recipients of the draft email.", + }, ], - category: "email" - } + category: "email", + }, ]; // GitHub Tools @@ -168,32 +415,89 @@ const githubTools: ToolDefinition[] = [ tool_name: "GitHub.GetUser", description: "Get information about the authenticated GitHub user.", parameters: [], - category: "development" + category: "development", }, { tool_name: "GitHub.ListRepositories", description: "List repositories accessible to the authenticated user.", parameters: [ - { name: "visibility", type: "string", required: false, description: "Filter by repository visibility. Options: 'all', 'public', 'private'.", default: "all" }, - { name: "sort", type: "string", required: false, description: "Sort repositories by. Options: 'created', 'updated', 'pushed', 'full_name'.", default: "full_name" }, - { name: "per_page", type: "integer", required: false, description: "Number of repositories per page.", default: 30 }, - { name: "page", type: "integer", required: false, description: "Page number for pagination.", default: 1 } + { + name: "visibility", + type: "string", + required: false, + description: + "Filter by repository visibility. Options: 'all', 'public', 'private'.", + default: "all", + }, + { + name: "sort", + type: "string", + required: false, + description: + "Sort repositories by. Options: 'created', 'updated', 'pushed', 'full_name'.", + default: "full_name", + }, + { + name: "per_page", + type: "integer", + required: false, + description: "Number of repositories per page.", + default: 30, + }, + { + name: "page", + type: "integer", + required: false, + description: "Page number for pagination.", + default: 1, + }, ], - category: "development" + category: "development", }, { tool_name: "GitHub.CreatePullRequest", description: "Create a new pull request in a repository.", parameters: [ - { name: "owner", type: "string", required: true, description: "The repository owner's username." }, - { name: "repo", type: "string", required: true, description: "The repository name." }, - { name: "title", type: "string", required: true, description: "The title of the pull request." }, - { name: "body", type: "string", required: false, description: "The description of the pull request." }, - { name: "head", type: "string", required: true, description: "The name of the branch where your changes are implemented." }, - { name: "base", type: "string", required: true, description: "The name of the branch you want the changes pulled into." } + { + name: "owner", + type: "string", + required: true, + description: "The repository owner's username.", + }, + { + name: "repo", + type: "string", + required: true, + description: "The repository name.", + }, + { + name: "title", + type: "string", + required: true, + description: "The title of the pull request.", + }, + { + name: "body", + type: "string", + required: false, + description: "The description of the pull request.", + }, + { + name: "head", + type: "string", + required: true, + description: + "The name of the branch where your changes are implemented.", + }, + { + name: "base", + type: "string", + required: true, + description: "The name of the branch you want the changes pulled into.", + }, ], - category: "development" - } + category: "development", + }, ]; // Notion Tools @@ -202,26 +506,80 @@ const notionTools: ToolDefinition[] = [ tool_name: "Notion.SearchPages", description: "Search for pages in Notion.", parameters: [ - { name: "query", type: "string", required: false, description: "The text to search for." }, - { name: "filter", type: "object", required: false, description: "Filter results by type. Options: { \"property\": \"object\", \"value\": \"page\" } or { \"property\": \"object\", \"value\": \"database\" }." }, - { name: "sort", type: "object", required: false, description: "Sort the results. Example: { \"direction\": \"ascending\", \"timestamp\": \"last_edited_time\" }." }, - { name: "page_size", type: "integer", required: false, description: "Number of results per page.", default: 100 }, - { name: "start_cursor", type: "string", required: false, description: "Pagination cursor." } + { + name: "query", + type: "string", + required: false, + description: "The text to search for.", + }, + { + name: "filter", + type: "object", + required: false, + description: + 'Filter results by type. Options: { "property": "object", "value": "page" } or { "property": "object", "value": "database" }.', + }, + { + name: "sort", + type: "object", + required: false, + description: + 'Sort the results. Example: { "direction": "ascending", "timestamp": "last_edited_time" }.', + }, + { + name: "page_size", + type: "integer", + required: false, + description: "Number of results per page.", + default: 100, + }, + { + name: "start_cursor", + type: "string", + required: false, + description: "Pagination cursor.", + }, ], - category: "productivity" + category: "productivity", }, { tool_name: "Notion.CreatePage", description: "Create a new page in Notion.", parameters: [ - { name: "parent_id", type: "string", required: true, description: "The ID of the parent page or database." }, - { name: "parent_type", type: "string", required: true, description: "Type of parent. Options: 'page_id', 'database_id'." }, - { name: "title", type: "string", required: true, description: "The title of the new page." }, - { name: "content", type: "array[object]", required: false, description: "The content blocks for the page." }, - { name: "properties", type: "object", required: false, description: "Properties for the page (required if parent is a database)." } + { + name: "parent_id", + type: "string", + required: true, + description: "The ID of the parent page or database.", + }, + { + name: "parent_type", + type: "string", + required: true, + description: "Type of parent. Options: 'page_id', 'database_id'.", + }, + { + name: "title", + type: "string", + required: true, + description: "The title of the new page.", + }, + { + name: "content", + type: "array[object]", + required: false, + description: "The content blocks for the page.", + }, + { + name: "properties", + type: "object", + required: false, + description: + "Properties for the page (required if parent is a database).", + }, ], - category: "productivity" - } + category: "productivity", + }, ]; // Spotify Tools @@ -230,29 +588,63 @@ const spotifyTools: ToolDefinition[] = [ tool_name: "Spotify.GetTrackFromId", description: "Get information about a track.", parameters: [ - { name: "track_id", type: "string", required: true, description: "The Spotify ID of the track." } + { + name: "track_id", + type: "string", + required: true, + description: "The Spotify ID of the track.", + }, ], - category: "music" + category: "music", }, { tool_name: "Spotify.PlayTrackByName", - description: "Plays a song by name. Note: This tool currently requires a self-hosted instance of Arcade.", + description: + "Plays a song by name. Note: This tool currently requires a self-hosted instance of Arcade.", parameters: [ - { name: "track_name", type: "string", required: true, description: "The name of the track to play." }, - { name: "artist_name", type: "string", required: false, description: "The name of the artist of the track." } + { + name: "track_name", + type: "string", + required: true, + description: "The name of the track to play.", + }, + { + name: "artist_name", + type: "string", + required: false, + description: "The name of the artist of the track.", + }, ], - category: "music" + category: "music", }, { tool_name: "Spotify.Search", - description: "Search Spotify catalog information. Note: This tool currently requires a self-hosted instance of Arcade.", + description: + "Search Spotify catalog information. Note: This tool currently requires a self-hosted instance of Arcade.", parameters: [ - { name: "q", type: "string", required: true, description: "The search query." }, - { name: "types", type: "array", required: true, description: "The types of results to return, Valid values are 'album', 'artist', 'playlist', 'track', 'show', 'episode', 'audiobook'." }, - { name: "limit", type: "integer", required: false, description: "The maximum number of results to return.", default: 1 } + { + name: "q", + type: "string", + required: true, + description: "The search query.", + }, + { + name: "types", + type: "array", + required: true, + description: + "The types of results to return, Valid values are 'album', 'artist', 'playlist', 'track', 'show', 'episode', 'audiobook'.", + }, + { + name: "limit", + type: "integer", + required: false, + description: "The maximum number of results to return.", + default: 1, + }, ], - category: "music" - } + category: "music", + }, ]; // Combine all tools @@ -266,12 +658,12 @@ const allTools: ToolDefinition[] = [ ...gmailTools, ...githubTools, ...notionTools, - ...spotifyTools + ...spotifyTools, ]; export const toolsConfig: ToolsConfig = { providers: [], - tools: allTools + tools: allTools, }; export type { ToolParameter, ToolDefinition, ToolProvider, ToolsConfig }; diff --git a/frontend/src/lib/tools-prompt-generator.ts b/frontend/src/lib/tools-prompt-generator.ts index ea14f9a..6411dbf 100644 --- a/frontend/src/lib/tools-prompt-generator.ts +++ b/frontend/src/lib/tools-prompt-generator.ts @@ -1,13 +1,14 @@ -import { toolsConfig, ToolParameter } from './tools-config'; +import { toolsConfig, ToolParameter } from "./tools-config"; export function generateToolsPrompt(): string { - let prompt = "# TIMEZONE\n\n- We are in the timezone: New York\n- Time now: {time}\n\n"; + let prompt = + "# TIMEZONE\n\n- We are in the timezone: New York\n- Time now: {time}\n\n"; // Group tools by category/provider const toolsByCategory: { [key: string]: any[] } = {}; - - toolsConfig.tools.forEach(tool => { - const category = tool.category || 'other'; + + toolsConfig.tools.forEach((tool) => { + const category = tool.category || "other"; if (!toolsByCategory[category]) { toolsByCategory[category] = []; } @@ -18,17 +19,19 @@ export function generateToolsPrompt(): string { Object.entries(toolsByCategory).forEach(([category, tools]) => { const categoryTitle = category.charAt(0).toUpperCase() + category.slice(1); prompt += `## ${categoryTitle}\n\n`; - - tools.forEach(tool => { + + tools.forEach((tool) => { prompt += `tool_name = "${tool.tool_name}"\n`; prompt += `${tool.description}\n\n`; - + if (tool.parameters && tool.parameters.length > 0) { prompt += "Parameters:\n\n"; tool.parameters.forEach((param: ToolParameter) => { const required = param.required ? "required" : "optional"; - const defaultValue = param.default ? `, Defaults to ${param.default}` : ""; - prompt += `- ${param.name} (${param.type}, ${required}${defaultValue}) ${param.description || ''}\n`; + const defaultValue = param.default + ? `, Defaults to ${param.default}` + : ""; + prompt += `- ${param.name} (${param.type}, ${required}${defaultValue}) ${param.description || ""}\n`; }); } else { prompt += "Parameters:\nThis tool takes no parameters.\n"; diff --git a/frontend/src/lib/tools-providers.ts b/frontend/src/lib/tools-providers.ts index e32f69a..5b15f58 100644 --- a/frontend/src/lib/tools-providers.ts +++ b/frontend/src/lib/tools-providers.ts @@ -1,4 +1,4 @@ -import { ToolProvider } from '../types/tools'; +import { ToolProvider } from "../types/tools"; import { GoogleIcon, GitHubIcon, @@ -6,7 +6,7 @@ import { SlackIcon, XIcon, SpotifyIcon, -} from '../components/ProviderIcons'; +} from "../components/ProviderIcons"; // Centralized tools configuration for providers export const toolsProviders: ToolProvider[] = [ diff --git a/frontend/src/lib/tools-utils.ts b/frontend/src/lib/tools-utils.ts index 59144df..4a3a159 100644 --- a/frontend/src/lib/tools-utils.ts +++ b/frontend/src/lib/tools-utils.ts @@ -1,28 +1,28 @@ -import { toolsConfig } from './tools-config'; +import { toolsConfig } from "./tools-config"; // Export tools list for backend consumption (e.g., coral_factory) export function getAvailableTools(): string[] { - return toolsConfig.tools.map(tool => tool.tool_name); + return toolsConfig.tools.map((tool) => tool.tool_name); } // Export tools by category for better organization export function getToolsByCategory(): { [category: string]: string[] } { const toolsByCategory: { [category: string]: string[] } = {}; - - toolsConfig.tools.forEach(tool => { - const category = tool.category || 'other'; + + toolsConfig.tools.forEach((tool) => { + const category = tool.category || "other"; if (!toolsByCategory[category]) { toolsByCategory[category] = []; } toolsByCategory[category].push(tool.tool_name); }); - + return toolsByCategory; } // Export individual tool definitions for detailed information export function getToolDefinition(toolName: string) { - return toolsConfig.tools.find(tool => tool.tool_name === toolName); + return toolsConfig.tools.find((tool) => tool.tool_name === toolName); } export default {