HEX
Server: LiteSpeed
System: Linux houston.panomity.com 6.8.0-100-generic #100-Ubuntu SMP PREEMPT_DYNAMIC Tue Jan 13 16:40:06 UTC 2026 x86_64
User: nudepix (1011)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //opt/agentcloud/webapp/src/components/TaskForm.tsx
'use strict';

import * as API from '@api';
import {
	HandRaisedIcon,
} from '@heroicons/react/20/solid';
import CreateAgentModal from 'components/CreateAgentModal';
import CreateToolModal from 'components/CreateToolModal';
import ToolSelectIcons from 'components/ToolSelectIcons';
import { useAccountContext } from 'context/account';
import Link from 'next/link';
import { useRouter } from 'next/router';
import React, { useEffect, useState } from 'react';
import Select from 'react-tailwindcss-select';
import { toast } from 'react-toastify';
import SelectClassNames from 'styles/SelectClassNames';

export default function TaskForm({ task = {}, tools = [], agents = [], datasources = [], editing, compact = false, callback, fetchTaskFormData }
	: { task?: any, tools?: any[], agents?: any[], datasources?: any[], editing?: boolean, compact?: boolean, callback?: Function, fetchTaskFormData?: Function }) {

	const [accountContext]: any = useAccountContext();
	const { account, csrf, teamName } = accountContext as any;
	const router = useRouter();
	const [modalOpen, setModalOpen]: any = useState(false);
	const { resourceSlug } = router.query;
	const [taskState, setTask] = useState(task);

	const { _id, name, description, expectedOutput, toolIds } = taskState;

	const initialTools = toolIds && toolIds
		.map(tid => {
			const foundTool = tools.find(t => t._id === tid);
			if (!foundTool) { return null; }
			return { label: foundTool.name, value: foundTool._id };
		})
		.filter(t => t);

	const preferredAgent = agents
		.find(a => a?._id === taskState?.agentId);

	useEffect(() => {
	    // Placeholder for any initial setup or effects
	}, []);

	async function taskPost(e) {
		e.preventDefault();
		const body: any = {
			_csrf: e.target._csrf.value,
			resourceSlug,
			name: e.target.name.value,
			description: e.target.description.value,
			expectedOutput: e.target.expectedOutput.value,
			toolIds: taskState?.toolIds || [],
			agentId: taskState?.agentId || null,
			asyncExecution: false, //e.target.asyncExecution.checked,
			requiresHumanInput: e.target.requiresHumanInput.checked,
		};
		if (editing) {
			await API.editTask(taskState._id, body, () => {
				toast.success('Task Updated');
			}, (res) => {
				toast.error(res);
			}, null);
		} else {
			const addedTask: any = await API.addTask(body, () => {
				toast.success('Added new task');
			}, (res) => {
				toast.error(res);
			}, compact ? null : router);
			callback && addedTask && callback(addedTask._id);
		}
	}

	const toolCallback = async (addedToolId) => {
		await fetchTaskFormData && fetchTaskFormData();
		setModalOpen(false);
		setTask(oldTask => {
			return {
				...oldTask,
				toolIds: [...(taskState?.toolIds||[]), addedToolId],
			};
		});
	};

	const agentCallback = async (addedAgentId) => {
		await fetchTaskFormData && fetchTaskFormData();
		setModalOpen(false);
		setTask(oldTask => {
			return {
				...oldTask,
				agentId: addedAgentId,
			};
		});
	};

	return (
		<>
			{modalOpen === 'agent'
				? <CreateAgentModal open={modalOpen !== false} setOpen={setModalOpen} callback={agentCallback} />
				: <CreateToolModal open={modalOpen !== false} setOpen={setModalOpen} callback={toolCallback} />}
			<form onSubmit={taskPost}>
				<input
					type='hidden'
					name='_csrf'
					value={csrf}
				/>
				<div className={`space-y-${compact ? '6' : '12'}`}>
					<div className='grid grid-cols-1 gap-x-8 gap-y-4 md:grid-cols-3'>
						<div className='col-span-full'>
							<label htmlFor='name' className='block text-sm font-medium leading-6 text-gray-900 dark:text-slate-400'>
								Name<span className='text-red-700'> *</span>
							</label>
							<input
								required
								type='text'
								id='name'
								name='name'
								className='block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6 dark:bg-slate-800 dark:ring-slate-600 dark:text-white'
								defaultValue={name}
							/>
						</div>

						<div className='col-span-full'>
							<label htmlFor='description' className='block text-sm font-medium leading-6 text-gray-900 dark:text-slate-400'>
								Task Description<span className='text-red-700'> *</span>
							</label>
							<textarea
								required
								id='description'
								name='description'
								placeholder='A clear, concise statement of what the task entails.'
								rows={4}
								className='block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6 dark:bg-slate-800 dark:ring-slate-600 dark:text-white'
								defaultValue={description}
							/>
						</div>

						<div className='col-span-full'>
							<label htmlFor='expectedOutput' className='block text-sm font-medium leading-6 text-gray-900 dark:text-slate-400'>
								Expected Output
							</label>
							<textarea
								id='expectedOutput'
								name='expectedOutput'
								placeholder='Clear and detailed definition of expected output for the task.'
								rows={4}
								className='block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6 dark:bg-slate-800 dark:ring-slate-600 dark:text-white'
								defaultValue={expectedOutput}
							/>
						</div>

						{/* Tool selection */}
						<div className='col-span-full'>
							<label htmlFor='toolIds' className='block text-sm font-medium leading-6 text-gray-900 dark:text-slate-400'>
								Tools
							</label>
							<Select
								isSearchable
								isClearable
								isMultiple
								primaryColor={'indigo'}
								classNames={SelectClassNames}
								value={taskState?.toolIds?.map(x => ({ value: x, label: tools.find(tx => tx._id === x)?.name}))}
								onChange={(v: any) => {
									if (v?.some(vals => vals.value === null)) {
										//Create new pressed
										return setModalOpen('tool');
									}
									setTask(oldTask => {
										return {
											...oldTask,
											toolIds: v?.map(x => x.value),
										};
									});
								}}
								options={tools.map(t => ({ label: t.name, value: t._id })).concat([{ label: '+ New Tool', value: null }])}
					            formatOptionLabel={data => {
									const optionTool = tools.find(oc => oc._id === data.value);
					                return (<li
										className={`flex align-items-center !overflow-visible transition duration-200 px-2 py-2 cursor-pointer select-none truncate rounded hover:bg-blue-100 hover:text-blue-500 overflow-visible ${
											data.isSelected
												? 'bg-blue-100 text-blue-500'
												: 'dark:text-white'
										}`}
									>
										<span className='tooltip z-100'>
											{ToolSelectIcons[optionTool?.type]}
											<span className='tooltiptext capitalize !w-[120px] !-ml-[60px]'>
												{optionTool?.type} tool
											</span>
										</span>
										<span className='ms-2 w-full overflow-hidden text-ellipsis'>{data.label}{optionTool ? ` - ${optionTool?.data?.description || optionTool?.description}` : ''}</span>
									</li>);
					            }}
							/>
						</div>

						{/* Preferred agent */}
						<div className='col-span-full'>
							<label htmlFor='preferredAgent' className='block text-sm font-medium leading-6 text-gray-900 dark:text-slate-400'>
									Preferred Agent
							</label>
							<div className='mt-2'>
								<Select
									isSearchable
						            primaryColor={'indigo'}
						            classNames={{
										menuButton: () => 'flex text-sm text-gray-500 dark:text-slate-400 border border-gray-300 rounded shadow-sm transition-all duration-300 focus:outline-none bg-white dark:bg-slate-800 dark:border-slate-600 hover:border-gray-400 focus:border-indigo-500 focus:ring focus:ring-indigo-500/20',
										menu: 'absolute z-10 w-full bg-white shadow-lg border rounded py-1 mt-1.5 text-sm text-gray-700 dark:bg-slate-700 dark:border-slate-600',
										list: 'dark:bg-slate-700',
										listGroupLabel: 'dark:bg-slate-700',
										listItem: (value?: { isSelected?: boolean }) => `block transition duration-200 px-2 py-2 cursor-pointer select-none truncate rounded dark:text-white ${value.isSelected ? 'text-white bg-indigo-500' : 'dark:hover:bg-slate-600'}`,
						            }}
						            value={preferredAgent ? { label: preferredAgent.name, value: preferredAgent._id } : null}
						            onChange={(v: any) => {
										if (v?.value == null) {
											return setModalOpen('agent');
										}
										setTask(oldTask => {
											return {
												...oldTask,
												agentId: v?.value,
											};
										});
        						   	}}
						            options={agents
						            	.map(a => ({ label: a.name, value: a._id, allowDelegation: a.allowDelegation })) // map to options
						            	.concat([{ label: '+ Create new agent', value: null, allowDelegation: false }])} // append "add new"
						            formatOptionLabel={(data: any) => {
						            	const optionAgent = agents.find(ac => ac._id === data.value);
						                return (<li
						                    className={`block transition duration-200 px-2 py-2 cursor-pointer select-none truncate rounded hover:bg-blue-100 hover:text-blue-500 justify-between flex hover:overflow-visible ${
						                        data.isSelected
						                            ? 'bg-blue-100 text-blue-500'
						                            : 'dark:text-white'
						                    }`}
						                >
						                    {data.label}{optionAgent ? ` - ${optionAgent.role}` : null} 
								            {data.allowDelegation && <span className='tooltip z-100'>
									            <span className='h-5 w-5 inline-flex items-center rounded-full bg-green-100 mx-1 px-2 py-1 text-xs font-semibold text-green-700'>
       												<HandRaisedIcon className='h-3 w-3 absolute -ms-1' />
       											</span>
							        			<span className='tooltiptext'>
													This agent allows automatic task delegation.
												</span>
											</span>}
						                </li>);
						            }}
						        />
							</div>
						</div>
						
						{/* Async execution checkbox 
						<div className='col-span-full'>
							<div className='mt-2'>
								<div className='sm:col-span-12'>
									<label htmlFor='asyncExecution' className='select-none flex items-center text-sm font-medium leading-6 text-gray-900 dark:text-slate-400'>
										<input
											type='checkbox'
											id='asyncExecution'
											name='asyncExecution'
											checked={taskState?.asyncExecution === true}
											onChange={e => {
												setTask(oldTask => {
													return {
														...oldTask,
														asyncExecution: e.target.checked,
													};
												});
											}}
											className='mr-2 h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500'
										/>
										Async Execution
									</label>
								</div>
							</div>
						</div>*/}
						
						{/* human_input tool checkbox */}
						<div className='col-span-full'>
							<div className='mt-2'>
								<div className='sm:col-span-12'>
									<label htmlFor='requiresHumanInput' className='select-none flex items-center text-sm font-medium leading-6 text-gray-900 dark:text-slate-400'>
										<input
											type='checkbox'
											id='requiresHumanInput'
											name='requiresHumanInput'
											checked={taskState?.requiresHumanInput === true}
											onChange={e => {
												setTask(oldTask => {
													return {
														...oldTask,
														requiresHumanInput: e.target.checked,
													};
												});
											}}
											className='mr-2 h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500'
										/>
										Allow Human Input
									</label>
								</div>
							</div>
						</div>

					</div>
				</div>

				<div className='mt-6 flex items-center justify-between gap-x-6'>
					{!compact && <Link href={`/${resourceSlug}/tasks`}>
						Back
					</Link>}
					<button
						type='submit'
						className={`rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 ${compact ? 'w-full' : ''}`}
					>
						Save
					</button>
				</div>
			</form>
		</>
	);
}