feat: fix agent performance, bugs, ui

This commit is contained in:
Saumya 2025-08-07 16:05:33 +05:30
parent a737299232
commit 07c088a932
2 changed files with 74 additions and 16 deletions

View File

@ -140,7 +140,15 @@ class CredentialProfileTool(AgentBuilderBaseTool):
if result.connected_account.redirect_url:
response_data["connection_link"] = result.connected_account.redirect_url
response_data["instructions"] = f"🔗 **IMPORTANT: Please visit the connection link to authenticate your {result.toolkit.name} account with this profile. After connecting, you'll be able to use {result.toolkit.name} tools in your agent.**"
# Include both the toolkit name and slug in a parseable format
# Format: [toolkit:slug:name] to help frontend identify the service accurately
response_data["instructions"] = f"""🔗 **{result.toolkit.name} Authentication Required**
Please authenticate your {result.toolkit.name} account by clicking the link below:
[toolkit:{toolkit_slug}:{result.toolkit.name}] Authentication: {result.connected_account.redirect_url}
After connecting, you'll be able to use {result.toolkit.name} tools in your agent."""
else:
response_data["instructions"] = f"This {result.toolkit.name} profile has been created and is ready to use."

View File

@ -87,34 +87,67 @@ function formatToolkitName(toolkitSlug: string): string {
}
function extractToolkitInfoFromContext(content: string, urlStartIndex: number): { toolkitName: string | null; toolkitSlug: string | null } {
// Look for toolkit information in the surrounding context
const contextBefore = content.substring(Math.max(0, urlStartIndex - 500), urlStartIndex);
const contextAfter = content.substring(urlStartIndex, Math.min(content.length, urlStartIndex + 200));
const fullContext = contextBefore + contextAfter;
let match = contextBefore.match(/\[toolkit:([^:]+):([^\]]+)\]\s+Authentication:\s*$/i);
if (match) {
const toolkitSlug = match[1].trim();
const toolkitName = match[2].trim();
return { toolkitName, toolkitSlug };
}
// Try to extract toolkit name from various patterns
match = contextBefore.match(/([A-Za-z]+(?:\s+[A-Za-z]+)*)\s+Authentication:\s*$/i);
if (match) {
const serviceName = match[1].trim();
const slug = serviceName.toLowerCase().replace(/\s+/g, '_');
return { toolkitName: serviceName, toolkitSlug: slug };
}
// Pattern 1: "Successfully created credential profile 'ProfileName' for ToolkitName"
let match = fullContext.match(/Successfully created credential profile[^f]*for\s+([^.!?\n]+)/i);
match = contextBefore.match(/\d+\.\s*([A-Za-z]+)\s+Authentication(?:\s+\([^)]*\))?\s*:?\s*$/i);
if (match) {
const serviceName = match[1].trim();
const slug = serviceName.toLowerCase().replace(/\s+/g, '_');
return { toolkitName: serviceName, toolkitSlug: slug };
}
match = contextBefore.match(/([A-Za-z]+)\s+Authentication\s+\(for[^)]*\)\s*:?\s*$/i);
if (match) {
const serviceName = match[1].trim();
const slug = serviceName.toLowerCase().replace(/\s+/g, '_');
return { toolkitName: serviceName, toolkitSlug: slug };
}
match = fullContext.match(/Successfully created credential profile[^f]*for\s+([^.!?\n]+)/i);
if (match) {
return { toolkitName: match[1].trim(), toolkitSlug: match[1].toLowerCase().replace(/\s+/g, '_') };
}
// Pattern 2: "connect your ToolkitName account"
match = fullContext.match(/connect your\s+([^a]+)\s+account/i);
if (match) {
const name = match[1].trim();
return { toolkitName: name, toolkitSlug: name.toLowerCase().replace(/\s+/g, '_') };
}
// Pattern 3: "authorize access to your ToolkitName account"
match = fullContext.match(/authorize access to your\s+([^a]+)\s+account/i);
if (match) {
const name = match[1].trim();
return { toolkitName: name, toolkitSlug: name.toLowerCase().replace(/\s+/g, '_') };
}
// Pattern 4: Look for common toolkit names in the context
match = fullContext.match(/Sign in to\s+([^.!?\n]+)/i);
if (match) {
const name = match[1].trim();
return { toolkitName: name, toolkitSlug: name.toLowerCase().replace(/\s+/g, '_') };
}
match = contextBefore.match(/([A-Za-z]+)\s+authentication\s*(?:link|url)?:?\s*$/i);
if (match) {
const serviceName = match[1].trim();
const slug = serviceName.toLowerCase().replace(/\s+/g, '_');
return { toolkitName: serviceName, toolkitSlug: slug };
}
const commonToolkits = Object.keys(TOOLKIT_NAME_MAPPINGS);
for (const toolkit of commonToolkits) {
const toolkitName = TOOLKIT_NAME_MAPPINGS[toolkit];
@ -127,26 +160,37 @@ function extractToolkitInfoFromContext(content: string, urlStartIndex: number):
}
function detectComposioUrls(content: string): ComposioUrl[] {
// Detect Composio authentication URLs (these are typically OAuth URLs from various providers)
const authUrlPatterns = [
// Google OAuth
/https:\/\/accounts\.google\.com\/oauth\/authorize\?[^\s)]+/g,
// GitHub OAuth
/https:\/\/accounts\.google\.com\/o\/oauth2\/[^\s)]+/g,
/https:\/\/github\.com\/login\/oauth\/authorize\?[^\s)]+/g,
// Generic OAuth pattern for other providers
/https:\/\/api\.notion\.com\/v1\/oauth\/authorize\?[^\s)]+/g,
/https:\/\/slack\.com\/oauth\/[^\s)]+/g,
/https:\/\/[^\/\s]+\.slack\.com\/oauth\/[^\s)]+/g,
/https:\/\/login\.microsoftonline\.com\/[^\s)]+/g,
/https:\/\/[^\/\s]+\/oauth2?\/authorize\?[^\s)]+/g,
// Composio backend URLs
/https:\/\/backend\.composio\.dev\/[^\s)]+/g,
// Any HTTPS URL that looks like an auth callback
/https:\/\/[^\/\s]+\/auth\/[^\s)]+/g,
/https:\/\/[^\/\s]+\/authorize\?[^\s)]+/g,
/https:\/\/[^\/\s]+\/connect\/[^\s)]+/g,
/https:\/\/[^\s)]+[?&](client_id|redirect_uri|response_type|scope)=[^\s)]+/g,
];
const urls: ComposioUrl[] = [];
const processedUrls = new Set<string>(); // To avoid duplicates
for (const pattern of authUrlPatterns) {
let match;
pattern.lastIndex = 0; // Reset regex state
while ((match = pattern.exec(content)) !== null) {
const url = match[0];
// Skip if we've already processed this URL
if (processedUrls.has(url)) {
continue;
}
processedUrls.add(url);
const { toolkitName, toolkitSlug } = extractToolkitInfoFromContext(content, match.index);
urls.push({
@ -164,7 +208,8 @@ function detectComposioUrls(content: string): ComposioUrl[] {
function hasAuthUrlPattern(content: string, url: ComposioUrl): boolean {
const beforeUrl = content.substring(Math.max(0, url.startIndex - 100), url.startIndex);
return /(?:authentication|auth|connect|visit)\s+(?:url|link):\s*$/i.test(beforeUrl);
// Updated pattern to also match [toolkit:slug:name] Authentication: format
return /(?:(?:\[toolkit:[^:]+:[^\]]+\]|[A-Za-z]+(?:\s+[A-Za-z]+)*)\s+)?(?:authentication|auth|connect|visit)\s+(?:url|link)?:\s*$/i.test(beforeUrl);
}
interface ComposioConnectButtonProps {
@ -259,7 +304,12 @@ export const ComposioUrlDetector: React.FC<ComposioUrlDetectorProps> = ({
const textBefore = content.substring(lastIndex, composioUrl.startIndex);
const cleanedTextBefore = hasAuthUrlPattern(content, composioUrl)
? textBefore.replace(/(?:authentication|auth|connect|visit)\s+(?:url|link):\s*$/i, '').trim()
? textBefore
// Remove [toolkit:slug:name] pattern
.replace(/\[toolkit:[^:]+:[^\]]+\]\s+/gi, '')
// Remove authentication/auth/connect/visit url/link patterns
.replace(/(?:authentication|auth|connect|visit)\s+(?:url|link)?:\s*$/i, '')
.trim()
: textBefore;
if (cleanedTextBefore.trim()) {