update event triggers

This commit is contained in:
Krishav Raj Singh 2025-09-24 02:32:49 +05:30
parent 6a210390c2
commit d5caa38e87
5 changed files with 242 additions and 364 deletions

View File

@ -4,7 +4,7 @@ import React, { useState } from 'react';
import { Zap } from 'lucide-react';
import { Dialog } from '@/components/ui/dialog';
import { ConfiguredTriggersList } from './configured-triggers-list';
import { TriggerConfigDialog } from './trigger-config-dialog';
import { TriggerCreationDialog } from '../../triggers/trigger-creation-dialog';
import { TriggerConfiguration, TriggerProvider } from './types';
import {
useAgentTriggers,
@ -155,16 +155,15 @@ export const AgentTriggersConfiguration: React.FC<AgentTriggersConfigurationProp
)}
{configuringProvider && (
<Dialog open={!!configuringProvider} onOpenChange={() => setConfiguringProvider(null)}>
<TriggerConfigDialog
provider={configuringProvider}
existingConfig={editingTrigger}
onSave={handleSaveTrigger}
onCancel={() => setConfiguringProvider(null)}
isLoading={createTriggerMutation.isPending || updateTriggerMutation.isPending}
agentId={agentId}
/>
</Dialog>
<TriggerCreationDialog
open={!!configuringProvider}
onOpenChange={() => setConfiguringProvider(null)}
type={configuringProvider.provider_id === 'schedule' ? 'schedule' : 'event'}
isEditMode={!!editingTrigger}
existingTrigger={editingTrigger}
onTriggerCreated={handleSaveTrigger}
onTriggerUpdated={handleSaveTrigger}
/>
)}
</div>
);

View File

@ -13,6 +13,7 @@ import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Loader2, Search, ArrowLeft, Info, Zap, ChevronRight, Plus, Sparkles, CheckCircle2, Link2 } from 'lucide-react';
import { useComposioAppsWithTriggers, useComposioAppTriggers, useCreateComposioEventTrigger, ComposioTriggerType } from '@/hooks/react-query/composio/use-composio-triggers';
import { useUpdateTrigger } from '@/hooks/react-query/triggers';
import { useComposioProfiles } from '@/hooks/react-query/composio/use-composio-profiles';
import { useComposioToolkitDetails } from '@/hooks/react-query/composio/use-composio';
import { toast } from 'sonner';
@ -26,6 +27,9 @@ interface EventBasedTriggerDialogProps {
onOpenChange: (open: boolean) => void;
agentId: string;
onTriggerCreated?: (triggerId: string) => void;
isEditMode?: boolean;
existingTrigger?: any; // TriggerConfiguration for edit mode
onTriggerUpdated?: (triggerId: string) => void;
}
type JSONSchema = {
@ -296,8 +300,16 @@ const DynamicConfigForm: React.FC<{
);
};
export const EventBasedTriggerDialog: React.FC<EventBasedTriggerDialogProps> = ({ open, onOpenChange, agentId, onTriggerCreated }) => {
const [step, setStep] = useState<'apps' | 'triggers' | 'config'>('apps');
export const EventBasedTriggerDialog: React.FC<EventBasedTriggerDialogProps> = ({
open,
onOpenChange,
agentId,
onTriggerCreated,
isEditMode = false,
existingTrigger,
onTriggerUpdated
}) => {
const [step, setStep] = useState<'apps' | 'triggers' | 'config'>(isEditMode ? 'config' : 'apps');
const [search, setSearch] = useState('');
const [selectedApp, setSelectedApp] = useState<{ slug: string; name: string; logo?: string } | null>(null);
const [selectedTrigger, setSelectedTrigger] = useState<ComposioTriggerType | null>(null);
@ -333,10 +345,11 @@ export const EventBasedTriggerDialog: React.FC<EventBasedTriggerDialogProps> = (
}, [allProfiles]);
const createTrigger = useCreateComposioEventTrigger();
const updateTrigger = useUpdateTrigger();
useEffect(() => {
if (!open) {
setStep('apps');
setStep(isEditMode ? 'config' : 'apps');
setSelectedApp(null);
setSelectedTrigger(null);
setConfig({});
@ -348,7 +361,7 @@ export const EventBasedTriggerDialog: React.FC<EventBasedTriggerDialogProps> = (
setWorkflowInput({});
setShowComposioConnector(false);
}
}, [open]);
}, [open, isEditMode]);
useEffect(() => {
if (selectedTrigger) {
@ -369,6 +382,65 @@ export const EventBasedTriggerDialog: React.FC<EventBasedTriggerDialogProps> = (
}
}, [profiles, profileId]);
// Initialize form for edit mode
useEffect(() => {
if (isEditMode && existingTrigger && open) {
console.log('Edit mode - existingTrigger:', existingTrigger);
const triggerConfig = existingTrigger.config || {};
console.log('Edit mode - triggerConfig:', triggerConfig);
// Set basic info
setName(existingTrigger.name || '');
setPrompt(triggerConfig.agent_prompt || '');
setProfileId(triggerConfig.profile_id || '');
setExecutionType(triggerConfig.execution_type || 'agent');
setSelectedWorkflowId(triggerConfig.workflow_id || '');
setWorkflowInput(triggerConfig.workflow_input || {});
// Set trigger config (excluding execution-specific fields)
const { agent_prompt, workflow_id, workflow_input, execution_type, profile_id, ...triggerSpecificConfig } = triggerConfig;
setConfig(triggerSpecificConfig);
// For composio triggers, we need to reconstruct the app and trigger selection
if (triggerConfig.provider_id === 'composio' && triggerConfig.trigger_slug) {
console.log('Edit mode - setting up composio trigger for:', triggerConfig.qualified_name, triggerConfig.trigger_slug);
// Extract toolkit slug from qualified_name (e.g., "composio.googledocs" -> "googledocs")
const toolkitSlug = triggerConfig.qualified_name?.replace('composio.', '') || '';
if (toolkitSlug) {
// Create app object to trigger the API call
const app = {
slug: toolkitSlug,
name: toolkitSlug,
logo: undefined
};
setSelectedApp(app);
}
}
}
}, [isEditMode, existingTrigger, open]);
// Find the matching trigger for edit mode once triggers are fetched
useEffect(() => {
if (isEditMode && existingTrigger && selectedApp && triggersData?.items) {
const triggerConfig = existingTrigger.config || {};
console.log('Edit mode - looking for trigger with slug:', triggerConfig.trigger_slug);
console.log('Edit mode - available triggers:', triggersData.items.map(t => t.slug));
if (triggerConfig.trigger_slug) {
// Find the matching trigger from the fetched data
const matchingTrigger = triggersData.items.find(t => t.slug === triggerConfig.trigger_slug);
if (matchingTrigger) {
console.log('Edit mode - found matching trigger:', matchingTrigger);
setSelectedTrigger(matchingTrigger);
} else {
console.log('Edit mode - no matching trigger found for slug:', triggerConfig.trigger_slug);
}
}
}
}, [isEditMode, existingTrigger, selectedApp, triggersData]);
const selectedWorkflow = useMemo(() => {
return (workflows || []).find((w: any) => w.id === selectedWorkflowId);
}, [workflows, selectedWorkflowId]);
@ -409,30 +481,61 @@ export const EventBasedTriggerDialog: React.FC<EventBasedTriggerDialogProps> = (
const handleCreate = async () => {
if (!agentId || !profileId || !selectedTrigger) return;
try {
const selectedProfile = profiles?.find(p => p.profile_id === profileId);
const base: any = {
agent_id: agentId,
profile_id: profileId,
slug: selectedTrigger.slug,
trigger_config: config,
name: name || `${selectedTrigger.toolkit.name}${executionType === 'agent' ? 'Agent' : 'Workflow'}`,
connected_account_id: selectedProfile?.connected_account_id,
toolkit_slug: selectedApp?.slug,
};
const payload = executionType === 'agent'
? { ...base, route: 'agent' as const, agent_prompt: (prompt || 'Read this') }
: { ...base, route: 'workflow' as const, workflow_id: selectedWorkflowId, workflow_input: workflowInput };
const result = await createTrigger.mutateAsync(payload);
toast.success('Task created');
if (isEditMode && existingTrigger) {
// Update existing trigger using the general update API
const updatedConfig = {
...config,
profile_id: profileId,
trigger_slug: selectedTrigger.slug,
qualified_name: `composio.${selectedApp?.slug}`,
provider_id: 'composio',
execution_type: executionType,
...(executionType === 'agent' ? { agent_prompt: prompt || 'Read this' } : {
workflow_id: selectedWorkflowId,
workflow_input: workflowInput
})
};
if (onTriggerCreated && result?.trigger_id) {
onTriggerCreated(result.trigger_id);
await updateTrigger.mutateAsync({
triggerId: existingTrigger.trigger_id,
name: name || `${selectedTrigger.toolkit.name}${executionType === 'agent' ? 'Agent' : 'Workflow'}`,
description: `Event trigger for ${selectedTrigger.toolkit.name}`,
config: updatedConfig,
is_active: true,
});
toast.success('Task updated');
if (onTriggerUpdated && existingTrigger.trigger_id) {
onTriggerUpdated(existingTrigger.trigger_id);
}
} else {
// Create new trigger using Composio-specific API
const selectedProfile = profiles?.find(p => p.profile_id === profileId);
const base: any = {
agent_id: agentId,
profile_id: profileId,
slug: selectedTrigger.slug,
trigger_config: config,
name: name || `${selectedTrigger.toolkit.name}${executionType === 'agent' ? 'Agent' : 'Workflow'}`,
connected_account_id: selectedProfile?.connected_account_id,
toolkit_slug: selectedApp?.slug,
};
const payload = executionType === 'agent'
? { ...base, route: 'agent' as const, agent_prompt: (prompt || 'Read this') }
: { ...base, route: 'workflow' as const, workflow_id: selectedWorkflowId, workflow_input: workflowInput };
const result = await createTrigger.mutateAsync(payload);
toast.success('Task created');
if (onTriggerCreated && result?.trigger_id) {
onTriggerCreated(result.trigger_id);
}
}
onOpenChange(false);
} catch (e: any) {
// Handle nested error structure from API
let errorMessage = 'Failed to create trigger';
let errorMessage = isEditMode ? 'Failed to update trigger' : 'Failed to create trigger';
console.error('Error creating trigger:', e);
console.error('Error details:', e?.details);
console.error('Error keys:', Object.keys(e || {}));
@ -486,7 +589,9 @@ export const EventBasedTriggerDialog: React.FC<EventBasedTriggerDialogProps> = (
<ArrowLeft className="h-4 w-4" />
</Button>
)}
<DialogTitle className="text-lg font-semibold">Create Event Trigger</DialogTitle>
<DialogTitle className="text-lg font-semibold">
{isEditMode ? 'Edit Event Trigger' : 'Create Event Trigger'}
</DialogTitle>
</div>
</DialogHeader>
<ProgressStepper currentStep={step} />
@ -612,12 +717,22 @@ export const EventBasedTriggerDialog: React.FC<EventBasedTriggerDialogProps> = (
</div>
)}
{step === 'config' && selectedTrigger && (
{step === 'config' && (
<div className="h-full flex flex-col">
<div
className="flex-1 overflow-y-auto p-6"
style={{ maxHeight: 'calc(90vh - 250px)' }}
>
{/* Loading state for edit mode while waiting for trigger data */}
{isEditMode && !selectedTrigger ? (
<div className="flex-1 flex items-center justify-center p-6">
<div className="text-center space-y-3">
<Loader2 className="h-8 w-8 animate-spin mx-auto text-muted-foreground" />
<p className="text-sm text-muted-foreground">Loading trigger configuration...</p>
</div>
</div>
) : selectedTrigger ? (
<>
<div
className="flex-1 overflow-y-auto p-6"
style={{ maxHeight: 'calc(90vh - 250px)' }}
>
<div className="max-w-2xl mx-auto space-y-6">
{selectedTrigger.instructions && (
<Markdown className="text-sm w-full text-muted-foreground">
@ -800,27 +915,29 @@ export const EventBasedTriggerDialog: React.FC<EventBasedTriggerDialogProps> = (
</div>
</div>
{/* Fixed Footer */}
{(!loadingProfiles && (profiles || []).filter(p => p.is_connected).length > 0) && (
<div className="shrink-0 border-t p-4 bg-background">
<div className="flex justify-end">
<Button
onClick={handleCreate}
disabled={createTrigger.isPending || !name.trim() || !profileId || !isConfigValid || (executionType === 'agent' ? !prompt.trim() : !selectedWorkflowId)}
size="sm"
>
{createTrigger.isPending ? (
<>
<Loader2 className="h-3 w-3 animate-spin mr-2" />
Creating...
</>
) : (
'Create Trigger'
)}
</Button>
</div>
</div>
)}
{/* Fixed Footer */}
{(!loadingProfiles && (profiles || []).filter(p => p.is_connected).length > 0) && (
<div className="shrink-0 border-t p-4 bg-background">
<div className="flex justify-end">
<Button
onClick={handleCreate}
disabled={(isEditMode ? updateTrigger.isPending : createTrigger.isPending) || !name.trim() || !profileId || !isConfigValid || (executionType === 'agent' ? !prompt.trim() : !selectedWorkflowId)}
size="sm"
>
{(isEditMode ? updateTrigger.isPending : createTrigger.isPending) ? (
<>
<Loader2 className="h-3 w-3 animate-spin mr-2" />
{isEditMode ? 'Updating...' : 'Creating...'}
</>
) : (
isEditMode ? 'Update Trigger' : 'Create Trigger'
)}
</Button>
</div>
</div>
)}
</>
) : null}
</div>
)}
</div>

View File

@ -1,276 +0,0 @@
"use client";
import React, { useState, useEffect } from 'react';
import {
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import { Switch } from '@/components/ui/switch';
import {
Activity,
Copy,
ExternalLink,
Loader2
} from 'lucide-react';
import { TriggerProvider, TriggerConfiguration, ScheduleTriggerConfig, EventTriggerConfig } from './types';
import { SimplifiedScheduleConfig } from './providers/simplified-schedule-config';
import { EventTriggerConfigForm } from './providers/event-config';
import { getDialogIcon } from './utils';
interface TriggerConfigDialogProps {
provider: TriggerProvider;
existingConfig?: TriggerConfiguration;
onSave: (config: any) => void;
onCancel: () => void;
isLoading?: boolean;
agentId: string;
selectedAgent?: string;
onAgentSelect?: (agentId: string) => void;
open?: boolean;
onOpenChange?: (open: boolean) => void;
}
export const TriggerConfigDialog: React.FC<TriggerConfigDialogProps> = ({
provider,
existingConfig,
onSave,
onCancel,
isLoading = false,
agentId,
selectedAgent,
onAgentSelect,
open = true,
onOpenChange
}) => {
const [name, setName] = useState(existingConfig?.name || '');
const [description, setDescription] = useState(existingConfig?.description || '');
const [isActive, setIsActive] = useState(existingConfig?.is_active ?? true);
const [config, setConfig] = useState(existingConfig?.config || {});
const [errors, setErrors] = useState<Record<string, string>>({});
useEffect(() => {
if (!name && !existingConfig) {
setName(`${provider.name} Trigger`);
}
}, [provider, existingConfig, name]);
const validateForm = () => {
const newErrors: Record<string, string> = {};
if (!name.trim()) {
newErrors.name = 'Name is required';
}
if (provider.provider_id === 'telegram') {
if (!config.bot_token) {
newErrors.bot_token = 'Bot token is required';
}
} else if (provider.provider_id === 'slack') {
if (!config.signing_secret) {
newErrors.signing_secret = 'Signing secret is required';
}
} else if (provider.provider_id === 'schedule') {
if (!config.cron_expression) {
newErrors.cron_expression = 'Cron expression is required';
}
if (config.execution_type === 'workflow') {
if (!config.workflow_id) {
newErrors.workflow_id = 'Workflow selection is required';
}
} else {
if (!config.agent_prompt) {
newErrors.agent_prompt = 'Agent prompt is required';
}
}
} else if (provider.trigger_type === 'webhook' || provider.provider_id === 'composio') {
// Validate event-based triggers
if (config.execution_type === 'workflow') {
if (!config.workflow_id) {
newErrors.workflow_id = 'Workflow selection is required';
}
} else {
if (!config.agent_prompt) {
newErrors.agent_prompt = 'Agent prompt is required';
}
}
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleSave = () => {
if (validateForm()) {
onSave({
name: name.trim(),
description: description.trim(),
is_active: isActive,
config,
});
}
};
if (provider.provider_id === 'schedule') {
return (
<SimplifiedScheduleConfig
provider={provider}
config={config as ScheduleTriggerConfig}
onChange={setConfig}
errors={errors}
agentId={agentId}
name={name}
description={description}
onNameChange={setName}
onDescriptionChange={setDescription}
isActive={isActive}
onActiveChange={setIsActive}
selectedAgent={selectedAgent}
onAgentSelect={onAgentSelect}
open={open}
onOpenChange={onOpenChange || onCancel}
onSave={onSave}
isEditMode={!!existingConfig}
/>
);
}
const renderProviderSpecificConfig = () => {
switch (provider.provider_id) {
case 'schedule':
return (
<SimplifiedScheduleConfig
provider={provider}
config={config as ScheduleTriggerConfig}
onChange={setConfig}
errors={errors}
agentId={agentId}
name={name}
description={description}
onNameChange={setName}
onDescriptionChange={setDescription}
isActive={isActive}
onActiveChange={setIsActive}
selectedAgent={selectedAgent}
onAgentSelect={onAgentSelect}
open={open}
onOpenChange={onOpenChange || onCancel}
onSave={onSave}
isEditMode={!!existingConfig}
/>
);
case 'composio':
return (
<EventTriggerConfigForm
provider={provider}
config={config as EventTriggerConfig}
onChange={setConfig}
errors={errors}
agentId={agentId}
name={name}
description={description}
onNameChange={setName}
onDescriptionChange={setDescription}
isActive={isActive}
onActiveChange={setIsActive}
/>
);
default:
if (provider.trigger_type === 'webhook') {
return (
<EventTriggerConfigForm
provider={provider}
config={config as EventTriggerConfig}
onChange={setConfig}
errors={errors}
agentId={agentId}
name={name}
description={description}
onNameChange={setName}
onDescriptionChange={setDescription}
isActive={isActive}
onActiveChange={setIsActive}
/>
);
}
return (
<div className="text-center py-8 text-muted-foreground">
<Activity className="h-12 w-12 mx-auto mb-4" />
<p>Configuration form for {provider.name} is not yet implemented.</p>
</div>
);
}
};
return (
<DialogContent className="sm:max-w-2xl max-h-[90vh] overflow-hidden p-0 flex flex-col">
<div className="flex-1 overflow-y-auto">
{renderProviderSpecificConfig()}
{/* {provider.webhook_enabled && existingConfig?.webhook_url && (
<div className="px-6 pb-6">
<div className="border-t pt-6">
<h3 className="text-sm font-medium mb-4">Webhook Information</h3>
<div className="space-y-2">
<Label>Webhook URL</Label>
<div className="flex items-center space-x-2">
<Input
value={existingConfig.webhook_url}
readOnly
className="font-mono text-sm"
/>
<Button
size="sm"
variant="outline"
onClick={() => navigator.clipboard.writeText(existingConfig.webhook_url!)}
>
<Copy className="h-4 w-4" />
</Button>
<Button
size="sm"
variant="outline"
onClick={() => window.open(existingConfig.webhook_url, '_blank')}
>
<ExternalLink className="h-4 w-4" />
</Button>
</div>
<p className="text-xs text-muted-foreground">
Use this URL to configure the webhook in {provider.name}
</p>
</div>
</div>
</div>
)} */}
</div>
<div className="flex-shrink-0 px-6 py-6 border-t bg-muted/20">
<div className="flex gap-3">
<Button
variant="outline"
onClick={onCancel}
disabled={isLoading}
className="px-8 h-11"
>
Cancel
</Button>
<Button
onClick={handleSave}
disabled={isLoading}
className="flex-1 h-11 text-base font-medium"
>
{isLoading ? (
<>
<Loader2 className="animate-spin rounded-full h-4 w-4 mr-2" />
{existingConfig ? 'Updating Task...' : 'Creating Task...'}
</>
) : (
`${existingConfig ? 'Update' : 'Create'} Task`
)}
</Button>
</div>
</div>
</DialogContent>
);
};

View File

@ -26,7 +26,7 @@ import {
import Link from 'next/link';
import { TriggerWithAgent } from '@/hooks/react-query/triggers/use-all-triggers';
import { useDeleteTrigger, useToggleTrigger, useUpdateTrigger } from '@/hooks/react-query/triggers';
import { TriggerConfigDialog } from '@/components/agents/triggers/trigger-config-dialog';
import { TriggerCreationDialog } from './trigger-creation-dialog';
import { useAgentWorkflows } from '@/hooks/react-query/agents/use-agent-workflows';
import { toast } from 'sonner';
import { cn } from '@/lib/utils';
@ -334,16 +334,14 @@ export function SimplifiedTriggerDetailPanel({ trigger, onClose }: SimplifiedTri
{/* Edit Dialog */}
{showEditDialog && (
<Dialog open={showEditDialog} onOpenChange={setShowEditDialog}>
<TriggerConfigDialog
provider={provider}
existingConfig={triggerConfig}
onSave={handleEditSave}
onCancel={() => setShowEditDialog(false)}
isLoading={updateMutation.isPending}
agentId={trigger.agent_id}
/>
</Dialog>
<TriggerCreationDialog
open={showEditDialog}
onOpenChange={setShowEditDialog}
type={isScheduled ? 'schedule' : 'event'}
isEditMode={true}
existingTrigger={triggerConfig}
onTriggerUpdated={handleEditSave}
/>
)}
{/* Delete Dialog */}

View File

@ -13,7 +13,7 @@ import { ArrowRight, Clock, PlugZap } from 'lucide-react';
import { EventBasedTriggerDialog } from '@/components/agents/triggers/event-based-trigger-dialog';
import { SimplifiedScheduleConfig } from '@/components/agents/triggers/providers/simplified-schedule-config';
import { ScheduleTriggerConfig } from '@/components/agents/triggers/types';
import { useCreateTrigger } from '@/hooks/react-query/triggers';
import { useCreateTrigger, useUpdateTrigger } from '@/hooks/react-query/triggers';
import { toast } from 'sonner';
import { AgentSelectionDropdown } from '@/components/agents/agent-selection-dropdown';
@ -22,13 +22,19 @@ interface TriggerCreationDialogProps {
onOpenChange: (open: boolean) => void;
type: 'schedule' | 'event';
onTriggerCreated?: (triggerId: string) => void;
isEditMode?: boolean;
existingTrigger?: any; // TriggerConfiguration for edit mode
onTriggerUpdated?: (triggerId: string) => void;
}
export function TriggerCreationDialog({
open,
onOpenChange,
type,
onTriggerCreated
onTriggerCreated,
isEditMode = false,
existingTrigger,
onTriggerUpdated
}: TriggerCreationDialogProps) {
const [selectedAgent, setSelectedAgent] = useState<string>('');
const [step, setStep] = useState<'agent' | 'config'>('agent');
@ -39,6 +45,19 @@ export function TriggerCreationDialog({
execution_type: 'agent'
});
const createTriggerMutation = useCreateTrigger();
const updateTriggerMutation = useUpdateTrigger();
// Initialize form for edit mode
React.useEffect(() => {
if (isEditMode && existingTrigger && open) {
setSelectedAgent(existingTrigger.agent_id || '');
setName(existingTrigger.name || '');
setDescription(existingTrigger.description || '');
setConfig(existingTrigger.config || { cron_expression: '', execution_type: 'agent' });
// Skip agent selection step in edit mode
setStep('config');
}
}, [isEditMode, existingTrigger, open]);
const scheduleProvider = {
provider_id: 'schedule',
@ -55,23 +74,40 @@ export function TriggerCreationDialog({
}
try {
const newTrigger = await createTriggerMutation.mutateAsync({
agentId: selectedAgent,
provider_id: 'schedule',
name: data.name || 'Scheduled Trigger',
description: data.description || 'Automatically scheduled trigger',
config: data.config,
});
toast.success('Schedule trigger created successfully');
if (isEditMode && existingTrigger) {
// Update existing trigger
await updateTriggerMutation.mutateAsync({
triggerId: existingTrigger.trigger_id,
name: data.name || 'Scheduled Trigger',
description: data.description || 'Automatically scheduled trigger',
config: data.config,
is_active: data.is_active,
});
toast.success('Schedule trigger updated successfully');
if (onTriggerCreated && newTrigger?.trigger_id) {
onTriggerCreated(newTrigger.trigger_id);
if (onTriggerUpdated && existingTrigger.trigger_id) {
onTriggerUpdated(existingTrigger.trigger_id);
}
} else {
// Create new trigger
const newTrigger = await createTriggerMutation.mutateAsync({
agentId: selectedAgent,
provider_id: 'schedule',
name: data.name || 'Scheduled Trigger',
description: data.description || 'Automatically scheduled trigger',
config: data.config,
});
toast.success('Schedule trigger created successfully');
if (onTriggerCreated && newTrigger?.trigger_id) {
onTriggerCreated(newTrigger.trigger_id);
}
}
handleClose();
} catch (error: any) {
toast.error(error.message || 'Failed to create schedule trigger');
console.error('Error creating schedule trigger:', error);
toast.error(error.message || `Failed to ${isEditMode ? 'update' : 'create'} schedule trigger`);
console.error(`Error ${isEditMode ? 'updating' : 'creating'} schedule trigger:`, error);
}
};
@ -97,17 +133,17 @@ export function TriggerCreationDialog({
{type === 'schedule' ? (
<>
<Clock className="h-5 w-5" />
Create Scheduled Task
{isEditMode ? 'Edit Scheduled Task' : 'Create Scheduled Task'}
</>
) : (
<>
<PlugZap className="h-5 w-5" />
Create App-based Task
{isEditMode ? 'Edit App-based Task' : 'Create App-based Task'}
</>
)}
</DialogTitle>
<DialogDescription>
First, select which agent should handle this task
{isEditMode ? 'Update the agent for this task' : 'First, select which agent should handle this task'}
</DialogDescription>
</DialogHeader>
@ -153,6 +189,7 @@ export function TriggerCreationDialog({
open={open}
onOpenChange={onOpenChange}
onSave={handleScheduleSave}
isEditMode={isEditMode}
/>
);
}
@ -163,6 +200,9 @@ export function TriggerCreationDialog({
onOpenChange={handleClose}
agentId={selectedAgent}
onTriggerCreated={onTriggerCreated}
isEditMode={isEditMode}
existingTrigger={existingTrigger}
onTriggerUpdated={onTriggerUpdated}
/>
);
}