This commit is contained in:
Bobbie 2025-10-08 16:35:02 +05:30 committed by GitHub
commit 89560ee66e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 940 additions and 0 deletions

View File

@ -0,0 +1,154 @@
import { parseToolResult } from '../tool-result-parser';
export interface TriggerData {
provider: string;
slug: string;
is_active: boolean;
}
export interface CreateEventTriggerData {
slug: string | null;
profile_id: string | null;
connected_account_id: string | null;
trigger_config: Record<string, any> | null;
name: string | null;
agent_prompt: string | null;
message: string | null;
trigger: TriggerData | null;
success?: boolean;
timestamp?: string;
}
const parseContent = (content: any): any => {
if (typeof content === 'string') {
try {
return JSON.parse(content);
} catch (e) {
return content;
}
}
return content;
};
export function extractCreateEventTriggerData(
assistantContent?: string,
toolContent?: any,
isSuccess?: boolean,
toolTimestamp?: string,
assistantTimestamp?: string
): CreateEventTriggerData & {
actualIsSuccess: boolean;
actualToolTimestamp: string | undefined;
actualAssistantTimestamp: string | undefined;
} {
const defaultResult: CreateEventTriggerData & {
actualIsSuccess: boolean;
actualToolTimestamp: string | undefined;
actualAssistantTimestamp: string | undefined;
} = {
slug: null,
profile_id: null,
connected_account_id: null,
trigger_config: null,
name: null,
agent_prompt: null,
message: null,
trigger: null,
actualIsSuccess: isSuccess || false,
actualToolTimestamp: toolTimestamp,
actualAssistantTimestamp: assistantTimestamp
};
try {
if (toolContent) {
let content = toolContent;
if (typeof toolContent === 'string') {
try {
content = JSON.parse(toolContent);
} catch (e) {
content = toolContent;
}
}
if (content && typeof content === 'object' && content.content) {
try {
const nestedContent = typeof content.content === 'string' ? JSON.parse(content.content) : content.content;
content = nestedContent;
} catch (e) {
}
}
if (content && typeof content === 'object' && content.tool_execution) {
const toolExecution = content.tool_execution;
if (toolExecution.result && toolExecution.result.success) {
const args = toolExecution.arguments;
const output = toolExecution.result.output;
if (args && output) {
return {
...defaultResult,
slug: args.slug || null,
profile_id: args.profile_id || null,
connected_account_id: args.connected_account_id || null,
trigger_config: args.trigger_config || null,
name: args.name || null,
agent_prompt: args.agent_prompt || null,
message: output.message || null,
trigger: output.trigger || null,
actualIsSuccess: true
};
}
}
}
if (content && typeof content === 'object' && content.tool === 'create-event-trigger') {
const parameters = content.parameters;
const output = content.output;
if (parameters && output) {
return {
...defaultResult,
slug: parameters.slug || null,
profile_id: parameters.profile_id || null,
connected_account_id: parameters.connected_account_id || null,
trigger_config: parameters.trigger_config || null,
name: parameters.name || null,
agent_prompt: parameters.agent_prompt || null,
message: output.message || null,
trigger: output.trigger || null,
actualIsSuccess: output.success !== false
};
}
}
}
if (assistantContent) {
const parsed = parseToolResult(assistantContent);
if (parsed && parsed.isSuccess) {
const toolOutput = parseContent(parsed.toolOutput);
const args = parsed.arguments;
if (args && toolOutput) {
return {
...defaultResult,
slug: args.slug || null,
profile_id: args.profile_id || null,
connected_account_id: args.connected_account_id || null,
trigger_config: args.trigger_config || null,
name: args.name || null,
agent_prompt: args.agent_prompt || null,
message: toolOutput.message || null,
trigger: toolOutput.trigger || null,
actualIsSuccess: true
};
}
}
}
return defaultResult;
} catch (error) {
console.error('Error extracting create event trigger data:', error);
return defaultResult;
}
}

View File

@ -0,0 +1,287 @@
import React from 'react';
import {
Zap,
CheckCircle,
AlertTriangle,
Bell,
Settings,
FileText,
Activity,
Play,
Link2,
Bot,
Code2
} from 'lucide-react';
import { ToolViewProps } from '../types';
import { formatTimestamp, getToolTitle } from '../utils';
import { cn } from '@/lib/utils';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { ScrollArea } from "@/components/ui/scroll-area";
import { LoadingState } from '../shared/LoadingState';
import { Separator } from "@/components/ui/separator";
import { extractCreateEventTriggerData } from './_utils';
export function CreateEventTriggerToolView({
name = 'create-event-trigger',
assistantContent,
toolContent,
assistantTimestamp,
toolTimestamp,
isSuccess = true,
isStreaming = false,
}: ToolViewProps) {
const {
slug,
profile_id,
connected_account_id,
trigger_config,
name: triggerName,
agent_prompt,
message,
trigger,
actualIsSuccess,
actualToolTimestamp,
actualAssistantTimestamp
} = extractCreateEventTriggerData(
assistantContent,
toolContent,
isSuccess,
toolTimestamp,
assistantTimestamp
);
const toolTitle = getToolTitle(name);
const formatSlugName = (slug: string): string => {
return slug
.replace(/_/g, ' ')
.split(' ')
.map(word => word.charAt(0) + word.slice(1).toLowerCase())
.join(' ');
};
const formatConfigKey = (key: string): string => {
return key
.replace(/([A-Z])/g, ' $1')
.replace(/_/g, ' ')
.split(' ')
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ')
.trim();
};
const formatConfigValue = (value: any): string => {
if (typeof value === 'object' && value !== null) {
return JSON.stringify(value, null, 2);
}
return String(value);
};
return (
<Card className="gap-0 flex border shadow-none border-t border-b-0 border-x-0 p-0 rounded-none flex-col h-full overflow-hidden bg-card">
<CardHeader className="h-14 bg-zinc-50/80 dark:bg-zinc-900/80 backdrop-blur-sm border-b p-2 px-4 space-y-2">
<div className="flex flex-row items-center justify-between">
<div className="flex items-center gap-2">
<div className="relative p-2 rounded-xl bg-gradient-to-br from-purple-500/20 to-purple-600/10 border border-purple-500/20">
<Zap className="w-5 h-5 text-purple-500 dark:text-purple-400" />
</div>
<div>
<CardTitle className="text-base font-medium text-zinc-900 dark:text-zinc-100">
{toolTitle}
</CardTitle>
</div>
</div>
{!isStreaming && (
<Badge
variant="secondary"
className={cn(
"text-xs font-medium",
actualIsSuccess
? "bg-emerald-50 text-emerald-700 border-emerald-200 dark:bg-emerald-900/20 dark:text-emerald-300 dark:border-emerald-800"
: "bg-red-50 text-red-700 border-red-200 dark:bg-red-900/20 dark:text-red-300 dark:border-red-800"
)}
>
{actualIsSuccess ? (
<CheckCircle className="h-3 w-3" />
) : (
<AlertTriangle className="h-3 w-3" />
)}
{actualIsSuccess ? 'Trigger created' : 'Creation failed'}
</Badge>
)}
</div>
</CardHeader>
<CardContent className="p-0 h-full flex-1 overflow-hidden relative">
{isStreaming ? (
<LoadingState
icon={Zap}
iconColor="text-purple-500 dark:text-purple-400"
bgColor="bg-gradient-to-b from-purple-100 to-purple-50 shadow-inner dark:from-purple-800/40 dark:to-purple-900/60 dark:shadow-purple-950/20"
title="Creating event trigger"
filePath={triggerName ? `"${triggerName}"` : undefined}
showProgress={true}
/>
) : actualIsSuccess && trigger ? (
<ScrollArea className="h-full w-full">
<div className="p-4 space-y-4">
<div className="border rounded-xl p-4 space-y-4">
<div className="flex items-start justify-between">
<div className="flex items-center gap-3">
<div className="w-12 h-12 rounded-xl bg-gradient-to-br from-purple-100 to-purple-50 dark:from-purple-900/40 dark:to-purple-800/20 border border-purple-200 dark:border-purple-800 flex items-center justify-center">
<Bell className="w-6 h-6 text-purple-600 dark:text-purple-400" />
</div>
<div>
<h3 className="font-semibold text-lg text-zinc-900 dark:text-zinc-100">
{triggerName || 'Event Trigger'}
</h3>
<p className="text-sm text-zinc-600 dark:text-zinc-400">
{slug ? formatSlugName(slug) : 'Custom Event'}
</p>
</div>
</div>
<div className="flex items-center gap-2">
<Badge
variant={trigger.is_active ? "default" : "secondary"}
className={cn(
"text-xs",
trigger.is_active
? "bg-green-100 text-green-700 border-green-200 dark:bg-green-900/20 dark:text-green-300 dark:border-green-800"
: "bg-gray-100 text-gray-700 border-gray-200 dark:bg-gray-900/20 dark:text-gray-300 dark:border-gray-800"
)}
>
{trigger.is_active ? (
<>
<Activity className="h-3 w-3 mr-1" />
Active
</>
) : 'Inactive'}
</Badge>
<Badge variant="outline" className="text-xs">
<Link2 className="h-3 w-3 mr-1" />
{trigger.provider || 'Provider'}
</Badge>
</div>
</div>
{message && (
<div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-3">
<p className="text-sm text-blue-800 dark:text-blue-200">
{message}
</p>
</div>
)}
<Separator />
<div className="grid grid-cols-2 gap-4">
<div className="space-y-1">
<div className="flex items-center gap-2 text-zinc-500 dark:text-zinc-400">
<Zap className="w-3 h-3" />
<span className="text-xs">Trigger Type</span>
</div>
<p className="text-sm font-medium text-zinc-900 dark:text-zinc-100 pl-5">
{trigger.slug || slug || 'Event Trigger'}
</p>
</div>
<div className="space-y-1">
<div className="flex items-center gap-2 text-zinc-500 dark:text-zinc-400">
<Play className="w-3 h-3" />
<span className="text-xs">Status</span>
</div>
<p className="text-sm font-medium text-zinc-900 dark:text-zinc-100 pl-5">
{trigger.is_active ? 'Running' : 'Stopped'}
</p>
</div>
</div>
</div>
{trigger_config && Object.keys(trigger_config).length > 0 && (
<div className="border rounded-xl p-4 space-y-3">
<div className="flex items-center gap-2">
<Settings className="w-4 h-4 text-zinc-600 dark:text-zinc-400" />
<h4 className="font-medium text-zinc-900 dark:text-zinc-100">
Trigger Configuration
</h4>
</div>
<div className="bg-zinc-50 dark:bg-zinc-800/50 rounded-lg p-3 space-y-2">
{Object.entries(trigger_config).map(([key, value]) => (
<div key={key} className="flex items-start gap-2">
<span className="text-sm font-medium text-zinc-700 dark:text-zinc-300 min-w-[120px]">
{formatConfigKey(key)}:
</span>
<span className="text-sm text-zinc-600 dark:text-zinc-400 font-mono break-all">
{formatConfigValue(value)}
</span>
</div>
))}
</div>
</div>
)}
{agent_prompt && (
<div className="border rounded-xl p-4 space-y-3">
<div className="flex items-center gap-2">
<Bot className="w-4 h-4 text-zinc-600 dark:text-zinc-400" />
<h4 className="font-medium text-zinc-900 dark:text-zinc-100">
Agent Execution Prompt
</h4>
</div>
<div className="bg-zinc-50 dark:bg-zinc-800/50 rounded-lg p-3">
<p className="text-sm text-zinc-700 dark:text-zinc-300 whitespace-pre-wrap">
{agent_prompt}
</p>
</div>
</div>
)}
{(connected_account_id || profile_id) && (
<div className="border rounded-xl p-4 space-y-3">
<div className="flex items-center gap-2">
<Code2 className="w-4 h-4 text-zinc-600 dark:text-zinc-400" />
<h4 className="font-medium text-zinc-900 dark:text-zinc-100">
Connection Details
</h4>
</div>
<div className="grid grid-cols-2 gap-4 text-sm">
{connected_account_id && (
<div className="space-y-1">
<span className="text-zinc-500 dark:text-zinc-400">Account ID</span>
<p className="font-mono text-zinc-700 dark:text-zinc-300">
{connected_account_id}
</p>
</div>
)}
{profile_id && (
<div className="space-y-1">
<span className="text-zinc-500 dark:text-zinc-400">Profile ID</span>
<p className="font-mono text-zinc-700 dark:text-zinc-300">
{profile_id}
</p>
</div>
)}
</div>
</div>
)}
<div className="bg-gradient-to-r from-purple-50 to-blue-50 dark:from-purple-900/20 dark:to-blue-900/20 rounded-lg p-4 border border-purple-200 dark:border-purple-800">
<div className="flex items-center gap-2 text-sm text-purple-700 dark:text-purple-400">
<div className="w-2 h-2 bg-purple-500 rounded-full animate-pulse" />
This trigger is now active and will automatically execute the agent when the configured event occurs.
</div>
</div>
</div>
</ScrollArea>
) : (
<div className="p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg m-4">
<p className="text-sm text-red-800 dark:text-red-200 flex items-center gap-2">
<AlertTriangle className="h-4 w-4" />
Failed to create event trigger. Please check your configuration and try again.
</p>
</div>
)}
</CardContent>
</Card>
);
}

View File

@ -0,0 +1,162 @@
import { parseToolResult } from '../tool-result-parser';
export interface TriggerConfig {
properties: Record<string, any>;
title?: string;
type?: string;
}
export interface TriggerPayload {
properties: Record<string, any>;
title?: string;
type?: string;
}
export interface ToolkitInfo {
slug: string;
name: string;
logo?: string;
}
export interface EventTrigger {
slug: string;
name: string;
description: string;
type: string;
instructions?: string;
toolkit?: ToolkitInfo;
config?: TriggerConfig;
payload?: TriggerPayload;
}
export interface ListAppEventTriggersData {
toolkit_slug: string | null;
message: string | null;
items: EventTrigger[];
toolkit: ToolkitInfo | null;
total: number;
success?: boolean;
timestamp?: string;
}
const parseContent = (content: any): any => {
if (typeof content === 'string') {
try {
return JSON.parse(content);
} catch (e) {
return content;
}
}
return content;
};
export function extractListAppEventTriggersData(
assistantContent?: string,
toolContent?: any,
isSuccess?: boolean,
toolTimestamp?: string,
assistantTimestamp?: string
): ListAppEventTriggersData & {
actualIsSuccess: boolean;
actualToolTimestamp: string | undefined;
actualAssistantTimestamp: string | undefined;
} {
const defaultResult: ListAppEventTriggersData & {
actualIsSuccess: boolean;
actualToolTimestamp: string | undefined;
actualAssistantTimestamp: string | undefined;
} = {
toolkit_slug: null,
message: null,
items: [],
toolkit: null,
total: 0,
actualIsSuccess: isSuccess || false,
actualToolTimestamp: toolTimestamp,
actualAssistantTimestamp: assistantTimestamp
};
try {
if (toolContent) {
let content = toolContent;
if (typeof toolContent === 'string') {
try {
content = JSON.parse(toolContent);
} catch (e) {
content = toolContent;
}
}
if (content && typeof content === 'object' && content.content) {
try {
const nestedContent = typeof content.content === 'string' ? JSON.parse(content.content) : content.content;
content = nestedContent;
} catch (e) {
}
}
if (content && typeof content === 'object' && content.tool_execution) {
const toolExecution = content.tool_execution;
if (toolExecution.result && toolExecution.result.success) {
const args = toolExecution.arguments;
const output = toolExecution.result.output;
if (args && output) {
return {
...defaultResult,
toolkit_slug: args.toolkit_slug || null,
message: output.message || null,
items: output.items || [],
toolkit: output.toolkit || null,
total: output.total || 0,
actualIsSuccess: true
};
}
}
}
if (content && typeof content === 'object' && content.tool === 'list-app-event-triggers') {
const parameters = content.parameters;
const output = content.output;
if (parameters && output) {
return {
...defaultResult,
toolkit_slug: parameters.toolkit_slug || null,
message: output.message || null,
items: output.items || [],
toolkit: output.toolkit || null,
total: output.total || 0,
actualIsSuccess: output.success !== false
};
}
}
}
if (assistantContent) {
const parsed = parseToolResult(assistantContent);
if (parsed && parsed.isSuccess) {
const toolOutput = parseContent(parsed.toolOutput);
const args = parsed.arguments;
if (args && toolOutput) {
return {
...defaultResult,
toolkit_slug: args.toolkit_slug || null,
message: toolOutput.message || null,
items: toolOutput.items || [],
toolkit: toolOutput.toolkit || null,
total: toolOutput.total || 0,
actualIsSuccess: true
};
}
}
}
return defaultResult;
} catch (error) {
console.error('Error extracting list app event triggers data:', error);
return defaultResult;
}
}

View File

@ -0,0 +1,322 @@
import React from 'react';
import {
Bell,
CheckCircle,
AlertTriangle,
Zap,
Clock,
Settings,
FileText,
Package,
Info,
Code2,
ChevronDown,
ChevronUp
} from 'lucide-react';
import { ToolViewProps } from '../types';
import { formatTimestamp, getToolTitle } from '../utils';
import { cn } from '@/lib/utils';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { ScrollArea } from "@/components/ui/scroll-area";
import { LoadingState } from '../shared/LoadingState';
import { Separator } from "@/components/ui/separator";
import { extractListAppEventTriggersData, EventTrigger } from './_utils';
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
export function ListAppEventTriggersToolView({
name = 'list-app-event-triggers',
assistantContent,
toolContent,
assistantTimestamp,
toolTimestamp,
isSuccess = true,
isStreaming = false,
}: ToolViewProps) {
const {
toolkit_slug,
message,
items,
toolkit,
total,
actualIsSuccess,
actualToolTimestamp,
actualAssistantTimestamp
} = extractListAppEventTriggersData(
assistantContent,
toolContent,
isSuccess,
toolTimestamp,
assistantTimestamp
);
const [expandedTriggers, setExpandedTriggers] = React.useState<Set<string>>(new Set());
const toolTitle = getToolTitle(name);
const toggleTrigger = (slug: string) => {
setExpandedTriggers(prev => {
const newSet = new Set(prev);
if (newSet.has(slug)) {
newSet.delete(slug);
} else {
newSet.add(slug);
}
return newSet;
});
};
const getTriggerTypeIcon = (type: string) => {
switch (type.toLowerCase()) {
case 'poll':
return <Clock className="w-3 h-3" />;
case 'webhook':
return <Zap className="w-3 h-3" />;
default:
return <Bell className="w-3 h-3" />;
}
};
const getTriggerTypeBadgeVariant = (type: string) => {
switch (type.toLowerCase()) {
case 'poll':
return "secondary";
case 'webhook':
return "default";
default:
return "outline";
}
};
const formatPropertyName = (key: string): string => {
return key
.replace(/([A-Z])/g, ' $1')
.replace(/_/g, ' ')
.split(' ')
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ')
.trim();
};
return (
<Card className="gap-0 flex border shadow-none border-t border-b-0 border-x-0 p-0 rounded-none flex-col h-full overflow-hidden bg-card">
<CardHeader className="h-14 bg-zinc-50/80 dark:bg-zinc-900/80 backdrop-blur-sm border-b p-2 px-4 space-y-2">
<div className="flex flex-row items-center justify-between">
<div className="flex items-center gap-2">
<div className="relative p-2 rounded-xl bg-gradient-to-br from-orange-500/20 to-orange-600/10 border border-orange-500/20">
<Bell className="w-5 h-5 text-orange-500 dark:text-orange-400" />
</div>
<div>
<CardTitle className="text-base font-medium text-zinc-900 dark:text-zinc-100">
{toolTitle}
</CardTitle>
</div>
</div>
{!isStreaming && (
<Badge
variant="secondary"
className={cn(
"text-xs font-medium",
actualIsSuccess
? "bg-emerald-50 text-emerald-700 border-emerald-200 dark:bg-emerald-900/20 dark:text-emerald-300 dark:border-emerald-800"
: "bg-red-50 text-red-700 border-red-200 dark:bg-red-900/20 dark:text-red-300 dark:border-red-800"
)}
>
{actualIsSuccess ? (
<CheckCircle className="h-3 w-3" />
) : (
<AlertTriangle className="h-3 w-3" />
)}
{actualIsSuccess ? 'Triggers loaded' : 'Failed to load'}
</Badge>
)}
</div>
</CardHeader>
<CardContent className="p-0 h-full flex-1 overflow-hidden relative">
{isStreaming ? (
<LoadingState
icon={Bell}
iconColor="text-orange-500 dark:text-orange-400"
bgColor="bg-gradient-to-b from-orange-100 to-orange-50 shadow-inner dark:from-orange-800/40 dark:to-orange-900/60 dark:shadow-orange-950/20"
title="Loading event triggers"
showProgress={true}
/>
) : actualIsSuccess && toolkit ? (
<ScrollArea className="h-full w-full">
<div className="p-4 space-y-4">
<div className="border rounded-xl p-4 space-y-4">
<div className="flex items-start justify-between">
<div className="flex items-center gap-3">
{toolkit.logo && (
<img
src={toolkit.logo}
alt={toolkit.name}
className="w-12 h-12 rounded-lg object-cover border border-zinc-200 dark:border-zinc-700"
/>
)}
<div>
<h3 className="font-semibold text-lg text-zinc-900 dark:text-zinc-100">
{toolkit.name} Event Triggers
</h3>
<p className="text-sm text-zinc-600 dark:text-zinc-400">
{message || `${total} trigger${total !== 1 ? 's' : ''} available`}
</p>
</div>
</div>
<Badge variant="outline" className="text-xs">
<Package className="w-3 h-3 mr-1" />
{toolkit_slug}
</Badge>
</div>
</div>
{items.length > 0 ? (
<div className="space-y-3">
{items.map((trigger, index) => (
<Collapsible
key={trigger.slug || index}
open={expandedTriggers.has(trigger.slug)}
>
<div className="border rounded-xl overflow-hidden">
<CollapsibleTrigger
onClick={() => toggleTrigger(trigger.slug)}
className="w-full p-4 hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-colors"
>
<div className="flex items-start justify-between">
<div className="flex items-start gap-3 text-left">
<div className="w-10 h-10 rounded-lg bg-gradient-to-br from-orange-100 to-orange-50 dark:from-orange-900/40 dark:to-orange-800/20 border border-orange-200 dark:border-orange-800 flex items-center justify-center">
<Zap className="w-5 h-5 text-orange-600 dark:text-orange-400" />
</div>
<div className="space-y-1">
<h4 className="font-medium text-zinc-900 dark:text-zinc-100">
{trigger.name}
</h4>
<p className="text-sm text-zinc-600 dark:text-zinc-400">
{trigger.description}
</p>
<div className="flex items-center gap-2 mt-2">
<Badge
variant={getTriggerTypeBadgeVariant(trigger.type)}
className="text-xs"
>
{getTriggerTypeIcon(trigger.type)}
<span className="ml-1">{trigger.type}</span>
</Badge>
<Badge variant="outline" className="text-xs">
{trigger.slug}
</Badge>
</div>
</div>
</div>
<div className="flex items-center">
{expandedTriggers.has(trigger.slug) ? (
<ChevronUp className="w-4 h-4 text-zinc-400" />
) : (
<ChevronDown className="w-4 h-4 text-zinc-400" />
)}
</div>
</div>
</CollapsibleTrigger>
<CollapsibleContent>
<div className="px-4 pb-4 space-y-4 border-t">
{trigger.instructions && (
<div className="mt-4 space-y-2">
<div className="flex items-center gap-2 text-sm font-medium text-zinc-700 dark:text-zinc-300">
<Info className="w-4 h-4" />
Instructions
</div>
<div className="text-sm text-zinc-600 dark:text-zinc-400 whitespace-pre-wrap bg-zinc-50 dark:bg-zinc-800/50 rounded-lg p-3">
{trigger.instructions.trim()}
</div>
</div>
)}
{trigger.config && trigger.config.properties && Object.keys(trigger.config.properties).length > 0 && (
<div className="space-y-2">
<div className="flex items-center gap-2 text-sm font-medium text-zinc-700 dark:text-zinc-300">
<Settings className="w-4 h-4" />
Configuration Parameters
</div>
<div className="bg-zinc-50 dark:bg-zinc-800/50 rounded-lg p-3 space-y-2">
{Object.entries(trigger.config.properties).map(([key, prop]: [string, any]) => (
<div key={key} className="space-y-1">
<div className="flex items-center gap-2">
<span className="text-xs font-medium text-zinc-700 dark:text-zinc-300">
{formatPropertyName(key)}
</span>
{prop.default !== undefined && (
<Badge variant="secondary" className="text-xs">
Default: {String(prop.default)}
</Badge>
)}
</div>
{prop.description && (
<p className="text-xs text-zinc-600 dark:text-zinc-400 pl-2">
{prop.description}
</p>
)}
{prop.examples && prop.examples.length > 0 && (
<div className="text-xs text-zinc-500 dark:text-zinc-500 pl-2">
Examples: {prop.examples.join(', ')}
</div>
)}
</div>
))}
</div>
</div>
)}
{trigger.payload && trigger.payload.properties && Object.keys(trigger.payload.properties).length > 0 && (
<div className="space-y-2">
<div className="flex items-center gap-2 text-sm font-medium text-zinc-700 dark:text-zinc-300">
<Code2 className="w-4 h-4" />
Payload Structure
</div>
<div className="bg-zinc-50 dark:bg-zinc-800/50 rounded-lg p-3 space-y-2">
{Object.entries(trigger.payload.properties).map(([key, prop]: [string, any]) => (
<div key={key} className="flex items-center justify-between">
<span className="text-xs font-mono text-zinc-700 dark:text-zinc-300">
{key}
</span>
<Badge variant="outline" className="text-xs">
{prop.type || 'any'}
</Badge>
</div>
))}
</div>
</div>
)}
</div>
</CollapsibleContent>
</div>
</Collapsible>
))}
</div>
) : (
<div className="border rounded-xl p-6 text-center">
<Bell className="w-12 h-12 mx-auto text-zinc-400 dark:text-zinc-600 mb-3" />
<p className="text-sm text-zinc-600 dark:text-zinc-400">
No event triggers found for {toolkit?.name || 'this toolkit'}
</p>
</div>
)}
</div>
</ScrollArea>
) : (
<div className="p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg m-4">
<p className="text-sm text-red-800 dark:text-red-200 flex items-center gap-2">
<AlertTriangle className="h-4 w-4" />
Failed to load event triggers. Please try again.
</p>
</div>
)}
</CardContent>
</Card>
);
}

View File

@ -86,6 +86,8 @@ export function getToolTitle(toolName: string): string {
'discover-user-mcp-servers': 'Discovering tools',
'configure-agent-integration': 'Configure Agent Integration',
'list-available-integrations': 'List Available Integrations',
'list-app-event-triggers': 'List Event Triggers',
'create-event-trigger': 'Create Event Trigger',
'create-agent-scheduled-trigger': 'Create Scheduled Trigger',
'list-agent-scheduled-triggers': 'List Scheduled Triggers',
'delete-agent-scheduled-trigger': 'Delete Scheduled Trigger',
@ -1312,6 +1314,10 @@ export function getToolComponent(toolName: string): string {
return 'UpdateAgentToolView';
case 'discover-user-mcp-servers':
return 'DiscoverUserMcpServersToolView';
case 'list-app-event-triggers':
return 'ListAppEventTriggersToolView';
case 'create-event-trigger':
return 'CreateEventTriggerToolView';
//Deploy
case 'deploy':

View File

@ -52,6 +52,8 @@ import { SearchMcpServersForAgentToolView } from '../search-mcp-servers-for-agen
import { CreateCredentialProfileForAgentToolView } from '../create-credential-profile-for-agent/create-credential-profile-for-agent';
import { DiscoverMcpToolsForAgentToolView } from '../discover-mcp-tools-for-agent/discover-mcp-tools-for-agent';
import { DiscoverUserMcpServersToolView } from '../discover-user-mcp-servers/discover-user-mcp-servers';
import { ListAppEventTriggersToolView } from '../list-app-event-triggers/list-app-event-triggers';
import { CreateEventTriggerToolView } from '../create-event-trigger/create-event-trigger';
import { ConfigureAgentIntegrationToolView } from '../configure-agent-integration/configure-agent-integration';
import CreateAgentScheduledTriggerToolView from '../create-agent-scheduled-trigger/create-agent-scheduled-trigger';
import { createPresentationViewerToolContent, parsePresentationSlidePath } from '../utils/presentation-utils';
@ -196,6 +198,8 @@ const defaultRegistry: ToolViewRegistryType = {
'create-credential-profile-for-agent': CreateCredentialProfileForAgentToolView,
'discover-mcp-tools-for-agent': DiscoverMcpToolsForAgentToolView,
'discover-user-mcp-servers': DiscoverUserMcpServersToolView,
'list-app-event-triggers': ListAppEventTriggersToolView,
'create-event-trigger': CreateEventTriggerToolView,
'configure-agent-integration': ConfigureAgentIntegrationToolView,
'create-agent-scheduled-trigger': CreateAgentScheduledTriggerToolView,
};

View File

@ -362,6 +362,11 @@ const TOOL_DISPLAY_NAMES = new Map([
['configure-mcp-server', 'Configuring MCP Server'],
['get-popular-mcp-servers', 'Getting Popular MCP Servers'],
['test-mcp-server-connection', 'Testing MCP Server Connection'],
['list_app_event_triggers', 'Finding event triggers'],
['list-app-event-triggers', 'Finding event triggers'],
['create-event-trigger', 'Creating event trigger'],
['create_event_trigger', 'Creating event trigger'],
['get-project-structure', 'Getting Project Structure'],
['build-project', 'Building Project'],