adding the new fields of crewAI to GraphQL schema and queries and UI forms + some UI enhancements

This commit is contained in:
Eng. Elias
2024-03-21 00:43:28 +04:00
parent 202483f47e
commit a654f454b8
14 changed files with 180 additions and 89 deletions

View File

@@ -65,6 +65,19 @@ const AgentsPage = () => {
</Alert>
</div>
)}
{data?.agents.length === 0 && (
<div className="w-full">
<Alert
color="cyan"
icon={
<Icon icon="material-symbols:warning-outline" fontSize={26} />
}
className="w-fit"
>
No Agents, Try to add one.
</Alert>
</div>
)}
{data?.agents.map((agent: Agent, i: number) => (
<div key={i} className="w-full lg:w-1/2 p-3 relative">
<div

View File

@@ -58,24 +58,13 @@ const resolvers = {
id: true,
},
});
const tasks = [];
for (let task of body.tasks) {
let agent = null;
if (task.agent) {
agent = crew.find((a) => a.id === task.agent) ?? null;
}
tasks.push({
...task,
agent,
});
}
const mission = await prisma.mission.create({
data: {
name,
verbose: !!verbose,
process: process ?? Process.SEQUENTIAL,
crew: { connect: crew },
tasks,
tasks: [],
result: "",
},
});

View File

@@ -16,6 +16,7 @@ const typeDefs = `#graphql
tools: [AgentTool!]!
allowDelegation: Boolean!
verbose: Boolean!
memory: Boolean
image: String
missions: [Mission!]
}
@@ -31,12 +32,14 @@ const typeDefs = `#graphql
type Task {
name: String!
description: String!
expected_output: String!
agent: Agent
}
input TaskInput {
name: String!
description: String!
expected_output: String!
agent: Int
}
@@ -74,8 +77,9 @@ const typeDefs = `#graphql
goal: String!
backstory: String
tools: [AgentTool!] = []
allowDelegation: Boolean = false
verbose: Boolean = false
allowDelegation: Boolean
verbose: Boolean
memory: Boolean
): Agent!
updateAgent(
@@ -86,6 +90,7 @@ const typeDefs = `#graphql
tools: [AgentTool!]
allowDelegation: Boolean
verbose: Boolean
memory: Boolean
): Agent!
deleteAgent(id: Int!): DeleteOutput
@@ -93,7 +98,6 @@ const typeDefs = `#graphql
createMission(
name: String!
crew: [Int!] = []
tasks: [TaskInput!] = []
verbose: Boolean = false
process: MissionProcess = "SEQUENTIAL"
): Mission!

View File

@@ -65,6 +65,19 @@ const MissionsPage = () => {
}}
/>
</div>
{data?.missions.length === 0 && (
<div className="w-full">
<Alert
color="cyan"
icon={
<Icon icon="material-symbols:warning-outline" fontSize={26} />
}
className="w-fit"
>
No missions, Try to add one.
</Alert>
</div>
)}
<div className="container m-auto flex flex-wrap flex-col md:flex-row items-center justify-start p-2">
{data?.missions.map((mission: Mission, i: number) => (
<div key={i} className=" w-full lg:w-1/2 p-3">

View File

@@ -4,7 +4,7 @@ import { selectTheme } from "@/data/consts";
import { Agent } from "@/types/agent";
import { Mission } from "@/types/mission";
import { Task } from "@/types/task";
import { Button } from "@material-tailwind/react";
import { Button, Input, Textarea } from "@material-tailwind/react";
import React, { useState } from "react";
import { TESelect } from "tw-elements-react";
@@ -20,13 +20,15 @@ const MissionTaskEditor: React.FC<MissionTaskEditorProps> = ({
onMissionChange,
}) => {
const [newTaskName, setNewTaskName] = useState("");
const [newTaskAgent, setNewTaskAgent] = useState<Agent | null>(null);
const [newTaskDescription, setNewTaskDescription] = useState("");
const [newTaskExpectedOutput, setNewTaskExpectedOutput] = useState("");
const [newTaskAgent, setNewTaskAgent] = useState<Agent | null>(null);
const handleAddTask = () => {
const newTask: Task = {
name: newTaskName,
description: newTaskDescription,
expected_output: newTaskExpectedOutput,
agent: newTaskAgent,
};
const updatedTasks = [...(mission?.tasks ?? []), newTask];
@@ -73,23 +75,31 @@ const MissionTaskEditor: React.FC<MissionTaskEditorProps> = ({
</div>
<div className="border border-t-0 border-success-400 rounded-b bg-success-100 px-4 py-3 text-success-700">
<div>
<label>Task Name: </label>
<input
type="text"
placeholder="Task Name"
<Input
label="Task Name"
color="green"
value={newTaskName}
onChange={(e) => setNewTaskName(e.target.value)}
className="border border-gray-300 text-black rounded px-3 py-1"
// className="border border-gray-300 text-black rounded px-3 py-1"
crossOrigin={undefined}
/>
</div>
<div className="my-2">
<Textarea
label="Task Description"
color="green"
resize={true}
value={newTaskDescription}
onChange={(e) => setNewTaskDescription(e.target.value)}
/>
</div>
<div>
<label>Task Description: </label>
<br />
<textarea
placeholder="Task Description"
value={newTaskDescription}
onChange={(e) => setNewTaskDescription(e.target.value)}
className="w-full border border-gray-300 text-black rounded px-3 py-1 ml-2"
<Textarea
label="Expected Output"
color="green"
resize={true}
value={newTaskExpectedOutput}
onChange={(e) => setNewTaskExpectedOutput(e.target.value)}
/>
</div>
<div className="m-2">

View File

@@ -12,13 +12,11 @@ import {
TEModalHeader,
TEModalBody,
TEModalFooter,
TEInput,
TETextarea,
TESelect,
} from "tw-elements-react";
import TWFileInput from "../inputs/file";
import { selectTheme } from "@/data/consts";
import { Button, Switch } from "@material-tailwind/react";
import { Button, Input, Switch, Textarea } from "@material-tailwind/react";
import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content";
import { DELETE_AGENT, UPDATE_AGENT } from "@/utils/graphql_queries";
@@ -174,9 +172,10 @@ export default function AgentModal(props: {
{isEdit && (
<div className="mb-4">
<label className="font-bold text-lg">Role:</label>
<TEInput
type="text"
className="mt-2"
<Input
label="Role"
color="blue"
className="text-white"
value={tempAgent?.role}
onChange={(event) => {
setTempAgent((prevState) => ({
@@ -184,15 +183,17 @@ export default function AgentModal(props: {
role: event.target.value,
}));
}}
crossOrigin={undefined}
/>
</div>
)}
<div className="mb-4">
<label className="font-bold text-lg">Goal:</label>
{isEdit ? (
<TEInput
type="text"
className="mt-2"
<Input
label="Goal"
color="blue"
className="text-white"
value={tempAgent?.goal}
onChange={(event) => {
setTempAgent((prevState) => ({
@@ -200,6 +201,7 @@ export default function AgentModal(props: {
goal: event.target.value,
}));
}}
crossOrigin={undefined}
/>
) : (
<div>{agent?.goal}</div>
@@ -208,8 +210,9 @@ export default function AgentModal(props: {
<div className="mb-4">
<label className="font-bold text-lg">Backstory:</label>
{isEdit ? (
<TETextarea
rows={4}
<Textarea
label="Backstory"
resize={true}
value={tempAgent?.backstory || ""}
onChange={(event) => {
setTempAgent((prevState) => ({
@@ -296,6 +299,29 @@ export default function AgentModal(props: {
/>
)}
</div>
<div className="flex items-center mb-4">
<label className="font-bold mx-2">Memory: </label>
{isEdit ? (
<Switch
crossOrigin={undefined}
color="blue"
defaultChecked={tempAgent?.memory}
onChange={(event) => {
setTempAgent((prevState) => ({
...prevState!,
memory: !!event.target.value,
}));
}}
/>
) : (
<Switch
crossOrigin={undefined}
color="blue"
defaultChecked={tempAgent?.memory}
disabled={true}
/>
)}
</div>
</div>
<div className="m-4 sm:w-1/2">
@@ -411,6 +437,7 @@ export default function AgentModal(props: {
handleUpdateAgent(tempAgent)
.then(() => {
setShowModal(false);
setEdit(false);
ReactSwal.fire({
title: "Updated",
text: "Agent updated successfully",

View File

@@ -10,14 +10,13 @@ import {
TEModalHeader,
TEModalBody,
TEModalFooter,
TEInput,
TESelect,
} from "tw-elements-react";
import { Mission } from "@/types/mission";
import MissionTaskEditor from "../inputs/mission_tasks_editor";
import { TasksAccordion } from "../ui/tasks_accordions";
import { Process, selectTheme } from "@/data/consts";
import { Alert, Button, Switch } from "@material-tailwind/react";
import { Alert, Button, Input, Switch } from "@material-tailwind/react";
import { useMutation, useQuery } from "@apollo/client";
import {
DELETE_MISSION,
@@ -139,9 +138,10 @@ export default function MissionModal(props: {
{isEdit && (
<div className="mb-4">
<label className="font-bold text-lg">Name:</label>
<TEInput
type="text"
className="mt-2"
<Input
label="Name"
color="blue"
className="text-white"
value={tempMission?.name}
onChange={(event) => {
setTempMission((prevState) => ({
@@ -149,6 +149,7 @@ export default function MissionModal(props: {
name: event.target.value,
}));
}}
crossOrigin={undefined}
/>
</div>
)}

View File

@@ -4,7 +4,6 @@ import { Agent } from "@/types/agent";
import { Icon } from "@iconify/react/dist/iconify.js";
import React, { useState } from "react";
import {
TEInput,
TEModal,
TEModalBody,
TEModalContent,
@@ -13,9 +12,8 @@ import {
TEModalHeader,
TERipple,
TESelect,
TETextarea,
} from "tw-elements-react";
import { Button, Switch } from "@material-tailwind/react";
import { Button, Input, Switch, Textarea } from "@material-tailwind/react";
import { useMutation } from "@apollo/client";
import { CREATE_AGENT } from "@/utils/graphql_queries";
import withReactContent from "sweetalert2-react-content";
@@ -41,23 +39,6 @@ function NewAgentModal(props: {
verbose: false,
});
const [selectedImage, setSelectedImage] = useState<
string | ArrayBuffer | null
>(null);
const handleImageChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event?.target?.files?.[0];
const reader = new FileReader();
reader.onloadend = () => {
setSelectedImage(reader.result);
};
if (file) {
reader.readAsDataURL(file);
}
};
const [createAgent] = useMutation(CREATE_AGENT);
const [createAgentLoading, setCreateAgentLoading] = useState(false);
@@ -95,9 +76,10 @@ function NewAgentModal(props: {
<div className="sm:w-1/2 mx-auto">
<div className="mb-4">
<label className="font-bold text-lg">Role:</label>
<TEInput
type="text"
className="mt-2"
<Input
label="Role"
color="blue"
className="text-white"
value={tempAgent?.role}
onChange={(event) => {
setTempAgent((prevState) => ({
@@ -105,13 +87,15 @@ function NewAgentModal(props: {
role: event.target.value,
}));
}}
crossOrigin={undefined}
/>
</div>
<div className="mb-4">
<label className="font-bold text-lg">Goal:</label>
<TEInput
type="text"
className="mt-2"
<Input
label="Goal"
color="blue"
className="text-white"
value={tempAgent?.goal}
onChange={(event) => {
setTempAgent((prevState) => ({
@@ -119,12 +103,15 @@ function NewAgentModal(props: {
goal: event.target.value,
}));
}}
crossOrigin={undefined}
/>
</div>
<div className="mb-4">
<label className="font-bold text-lg">Backstory:</label>
<TETextarea
rows={4}
<Textarea
label="Backstory"
color="blue"
resize={true}
value={tempAgent?.backstory || ""}
onChange={(event) => {
setTempAgent((prevState) => ({
@@ -179,6 +166,20 @@ function NewAgentModal(props: {
}}
/>
</div>
<div className="flex items-center mb-4">
<label className="font-bold mx-2">Memory: </label>
<Switch
crossOrigin={undefined}
color="blue"
defaultChecked={tempAgent?.verbose}
onChange={(event) => {
setTempAgent((prevState) => ({
...prevState!,
memory: !!event.target.value,
}));
}}
/>
</div>
</div>
</div>
</TEModalBody>

View File

@@ -1,10 +1,9 @@
import { Process, selectTheme } from "@/data/consts";
import { Mission } from "@/types/mission";
import { Icon } from "@iconify/react/dist/iconify.js";
import { Alert, Button, Switch } from "@material-tailwind/react";
import { Alert, Button, Input, Switch } from "@material-tailwind/react";
import React, { useState } from "react";
import {
TEInput,
TEModal,
TEModalBody,
TEModalContent,
@@ -14,7 +13,6 @@ import {
TERipple,
TESelect,
} from "tw-elements-react";
import MissionTaskEditor from "../inputs/mission_tasks_editor";
import { useMutation, useQuery } from "@apollo/client";
import { CREATE_MISSION, GET_AGENTS } from "@/utils/graphql_queries";
import { Agent } from "@/types/agent";
@@ -87,9 +85,10 @@ function NewMissionModal(props: {
<div>
<div className="mb-4">
<label className="font-bold text-lg">Name:</label>
<TEInput
type="text"
className="mt-2"
<Input
label="Name"
color="blue"
className="text-white"
value={tempMission?.name}
onChange={(event) => {
setTempMission((prevState) => ({
@@ -97,6 +96,7 @@ function NewMissionModal(props: {
name: event.target.value,
}));
}}
crossOrigin={undefined}
/>
</div>
<div className="mb-4">

View File

@@ -3,6 +3,7 @@ import {
Accordion,
AccordionHeader,
AccordionBody,
Typography,
} from "@material-tailwind/react";
import { Task } from "@/types/task";
@@ -33,7 +34,19 @@ export function TasksAccordion({ tasks }: { tasks: Array<Task> }) {
{task.agent?.role ?? "No Agent"}
</span>
</div>
<div>{task.description}</div>
<div>
<Typography variant="lead" placeholder={undefined}>
{task.description}
</Typography>
</div>
<div>
<Typography variant="h3" placeholder={undefined}>
Expected Output
</Typography>
<Typography variant="paragraph" placeholder={undefined}>
{task.expected_output}
</Typography>
</div>
</AccordionBody>
</Accordion>
))}

View File

@@ -53,6 +53,7 @@ export const tools = [
{ text: "WIKIPEDIA", value: "WIKIPEDIA" },
{ text: "YAHOO_FINANCE", value: "YAHOO_FINANCE" },
{ text: "YUOUTUBE_SEARCH", value: "YUOUTUBE_SEARCH" },
{ text: "CodeDocsSearchTool", value: "CodeDocsSearchTool" },
];
const game = `
@@ -74,9 +75,9 @@ export const missions: Array<Mission> = [
Instructions
------------
${game}
Your Final answer must be the full python code, only the python code and nothing else.
`,
expected_output:
"Your Final answer must be the full python code, only the python code and nothing else.",
agent: agents[0],
},
{
@@ -91,9 +92,9 @@ export const missions: Array<Mission> = [
Using the code you got, check for errors. Check for logic errors,
syntax errors, missing imports, variable declarations, mismatched brackets,
and security vulnerabilities.
Your Final answer must be the full python code, only the python code and nothing else.
`,
expected_output:
"Your Final answer must be the full python code, only the python code and nothing else.",
agent: agents[1],
},
{
@@ -107,9 +108,9 @@ export const missions: Array<Mission> = [
You will look over the code to insure that it is complete and
does the job that it is supposed to do.
Your Final answer must be the full python code, only the python code and nothing else.
`,
expected_output:
"Your Final answer must be the full python code, only the python code and nothing else.",
agent: agents[2],
},
],
@@ -124,11 +125,13 @@ export const missions: Array<Mission> = [
{
name: "Task1",
description: "description description description description",
expected_output: "Expected Output",
agent: agents[0],
},
{
name: "Task2",
description: "description description description description",
expected_output: "Expected Output",
},
],
verbose: true,
@@ -142,11 +145,13 @@ export const missions: Array<Mission> = [
{
name: "Task1",
description: "description description description description",
expected_output: "Expected Output",
agent: agents[0],
},
{
name: "Task2",
description: "description description description description",
expected_output: "Expected Output",
},
],
verbose: true,

View File

@@ -14,5 +14,6 @@ export type Agent = {
tools: Array<Tool>;
allowDelegation: boolean;
verbose: boolean;
memory?: boolean;
image?: string | null;
};

View File

@@ -9,5 +9,6 @@ export type TaskInput = {
export type Task = {
name: string;
description: string;
expected_output: string;
agent?: Agent | null;
};

View File

@@ -10,6 +10,7 @@ export const GET_AGENTS = gql`
tools
allowDelegation
verbose
memory
image
}
}
@@ -25,6 +26,7 @@ export const GET_AGENT_BY_ID = gql`
tools
allowDelegation
verbose
memory
image
missions {
id
@@ -42,6 +44,7 @@ export const CREATE_AGENT = gql`
$tools: [AgentTool!]
$allowDelegation: Boolean!
$verbose: Boolean!
$memory: Boolean
) {
createAgent(
role: $role
@@ -50,6 +53,7 @@ export const CREATE_AGENT = gql`
tools: $tools
allowDelegation: $allowDelegation
verbose: $verbose
memory: $memory
) {
id
role
@@ -72,6 +76,7 @@ export const UPDATE_AGENT = gql`
$tools: [AgentTool!]
$allowDelegation: Boolean
$verbose: Boolean
$memory: Boolean
) {
updateAgent(
id: $id
@@ -81,6 +86,7 @@ export const UPDATE_AGENT = gql`
tools: $tools
allowDelegation: $allowDelegation
verbose: $verbose
memory: $memory
) {
id
role
@@ -89,6 +95,7 @@ export const UPDATE_AGENT = gql`
tools
allowDelegation
verbose
memory
image
}
}
@@ -115,11 +122,13 @@ export const GET_MISSIONS = gql`
tools
allowDelegation
verbose
memory
image
}
tasks {
name
description
expected_output
agent {
id
role
@@ -145,11 +154,13 @@ export const GET_MISSION_BY_ID = gql`
tools
allowDelegation
verbose
memory
image
}
tasks {
name
description
expected_output
agent {
id
role
@@ -166,14 +177,12 @@ export const CREATE_MISSION = gql`
mutation CreateMission(
$name: String!
$crew: [Int!]
$tasks: [TaskInput!]
$verbose: Boolean
$process: MissionProcess
) {
createMission(
name: $name
crew: $crew
tasks: $tasks
verbose: $verbose
process: $process
) {
@@ -187,11 +196,13 @@ export const CREATE_MISSION = gql`
tools
allowDelegation
verbose
memory
image
}
tasks {
name
description
expected_output
agent {
id
role
@@ -209,7 +220,7 @@ export const UPDATE_MISSION = gql`
$id: Int!
$name: String
$crew: [Int!]
$tasks: [TaskInput!]
$tasks: [Task!]
$verbose: Boolean
$process: MissionProcess
) {
@@ -231,11 +242,13 @@ export const UPDATE_MISSION = gql`
tools
allowDelegation
verbose
memory
image
}
tasks {
name
description
expected_output
agent {
id
role