Agent and Mission GraphQL CRUD operations

This commit is contained in:
Eng. Elias
2024-02-20 17:06:45 +04:00
parent e6f08d85fc
commit 619f199abe
13 changed files with 1744 additions and 59 deletions

View File

@@ -0,0 +1,167 @@
import { Process } from "@/data/consts";
import { Agent } from "@/types/agent";
import { CreateMissionInput, Mission } from "@/types/mission";
import { Task } from "@/types/task";
import prisma from "@/utils/prisma";
import { GraphQLResolveInfo } from "graphql";
import { NextRequest, NextResponse } from "next/server";
const resolvers = {
Query: {
agents: () => {
return prisma.agent.findMany();
},
agent: (id: number) => {
return prisma.agent.findFirst({
where: {
id: id,
},
});
},
missions: async () => {
const missions = await prisma.mission.findMany({
include: {
crew: true,
},
});
return missions;
},
mission: (id: number) => {
return prisma.mission.findFirst({
where: {
id: id,
},
});
},
},
Mutation: {
createAgent: async (
parent: any,
body: Agent,
context: { req: NextRequest; res: NextResponse; datasource: any },
info: GraphQLResolveInfo
) => {
const agent = await prisma.agent.create({ data: body });
return agent;
},
updateAgent: async (
parent: any,
body: Agent,
context: { req: NextRequest; res: NextResponse; datasource: any },
info: GraphQLResolveInfo
) => {
const updatedAgent = await prisma.agent.update({
where: { id: body.id },
data: body,
});
return updatedAgent;
},
deleteAgent: async (
parent: any,
body: { id: number },
context: { req: NextRequest; res: NextResponse; datasource: any },
info: GraphQLResolveInfo
) => {
await prisma.agent.delete({ where: { id: body.id } });
return { deleted: true };
},
createMission: async (
parent: any,
body: CreateMissionInput,
context: { req: NextRequest; res: NextResponse; datasource: any },
info: GraphQLResolveInfo
) => {
const { name, verbose, process } = body;
const crew = await prisma.agent.findMany({
where: {
id: {
in: body.crew,
},
},
});
const tasks: Array<Task> = [];
for (let task of body.tasks) {
const agent = await prisma.agent.findFirst({
where: { id: task.agent },
});
tasks.push({
...task,
agent,
});
}
const mission = await prisma.mission.create({
data: {
name,
verbose: !!verbose,
process: process ?? Process.SEQUENTIAL,
crew: { create: crew },
tasks,
result: "",
},
});
mission.id;
return mission;
},
updateMission: async (
parent: any,
body: CreateMissionInput,
context: { req: NextRequest; res: NextResponse; datasource: any },
info: GraphQLResolveInfo
) => {
const { id, name, verbose, process } = body;
const crew = await prisma.agent.findMany({
where: {
id: {
in: body.crew,
},
},
});
const tasks: Array<Task> = [];
if (body.tasks) {
for (let task of body.tasks) {
const agent = await prisma.agent.findFirst({
where: { id: task.agent },
});
tasks.push({
...task,
agent,
});
}
}
const mission = await prisma.mission.update({
where: {
id,
},
include: {
crew: true,
},
data: {
name,
verbose: verbose,
process: process,
crew: { set: crew.map((agent) => ({ id: agent.id })) },
tasks,
result: "",
},
});
return mission;
},
deleteMission: async (
parent: any,
body: { id: number },
context: { req: NextRequest; res: NextResponse; datasource: any },
info: GraphQLResolveInfo
) => {
await prisma.mission.delete({ where: { id: body.id } });
return { deleted: true };
},
runMission: async (
parent: any,
body: { id: number },
context: { req: NextRequest; res: NextResponse; datasource: any },
info: GraphQLResolveInfo
) => {},
},
};
export default resolvers;

View File

@@ -0,0 +1,24 @@
import { startServerAndCreateNextHandler } from "@as-integrations/next";
import { ApolloServer } from "@apollo/server";
import { NextRequest, NextResponse } from "next/server";
import typeDefs from "./schema";
import resolvers from "./resolvers";
const server = new ApolloServer<object>({
resolvers,
typeDefs,
});
const handler = startServerAndCreateNextHandler<NextRequest>(server, {
context: async (req, res) => ({
req,
res,
dataSources: {},
}),
});
export async function GET(request: NextRequest) {
return handler(request);
}
export async function POST(request: NextRequest) {
return handler(request);
}

View File

@@ -0,0 +1,113 @@
const typeDefs = `#graphql
enum AgentTool {
DUCK_DUCK_GO_SEARCH
PUBMED
PYTHON_REPL
SEMANTIC_SCHOLER
STACK_EXCHANGE
WIKIDATA
WIKIPEDIA
YAHOO_FINANCE
YUOUTUBE_SEARCH
}
type Agent {
id: ID!
role: String!
goal: String!
backstory: String
tools: [AgentTool!]!
allowDelegation: Boolean!
verbose: Boolean!
image: String
missions: [Mission!]
}
input AgentInput {
id: ID!
}
type DeleteOutput {
deleted: Boolean!
}
type Task {
name: String!
description: String!
agent: Agent!
}
input TaskInput {
name: String!
description: String!
agent: Int
}
type Mission {
id: ID!
name: String!
crew: [Agent!]
tasks: [Task]
verbose: Boolean
process: MissionProcess
result: String
}
enum MissionProcess {
SEQUENTIAL
HIERARCHICAL
}
type Query {
agents(filter: String): [Agent!]!
agent(id: Int!): Agent
missions(filter: String): [Mission!]!
mission(id: Int!): Mission
}
type Mutation {
createAgent(
role: String!
goal: String!
backstory: String
tools: [AgentTool!] = []
allowDelegation: Boolean = false
verbose: Boolean = false
): Agent!
updateAgent(
id: Int!
role: String
goal: String
backstory: String
tools: [AgentTool!]
allowDelegation: Boolean
verbose: Boolean
): Agent!
deleteAgent(id: Int!): DeleteOutput
createMission(
name: String!
crew: [Int!] = []
tasks: [TaskInput!] = []
verbose: Boolean = false
process: MissionProcess = "SEQUENTIAL"
): Mission!
updateMission(
id: Int!
name: String
crew: [Int!]
tasks: [TaskInput!]
verbose: Boolean
process: MissionProcess
): Mission
deleteMission(id: Int!): DeleteOutput
runMission(id: Int!): Mission
}
`;
export default typeDefs;

4
src/data/consts.ts Normal file
View File

@@ -0,0 +1,4 @@
export enum Process {
SEQUENTIAL = "SEQUENTIAL",
HIERARCHICAL = "HIERARCHICAL",
}

View File

@@ -9,7 +9,7 @@ export const agents: Array<Agent> = [
Your expertise in programming in python. and do your best to
produce perfect code
`,
tools: ["tool1", "tool2"],
tools: ["DUCK_DUCK_GO_SEARCH", "PYTHON_REPL", "STACK_EXCHANGE"],
allowDelegation: false,
verbose: true,
image:

View File

@@ -1,9 +1,21 @@
type Tool =
| "DUCK_DUCK_GO_SEARCH"
| "PUBMED"
| "PYTHON_REPL"
| "SEMANTIC_SCHOLER"
| "STACK_EXCHANGE"
| "WIKIDATA"
| "WIKIPEDIA"
| "YAHOO_FINANCE"
| "YUOUTUBE_SEARCH";
export type Agent = {
id?: number;
role: string;
goal: string;
backstory: string;
tools: Array<string>;
backstory?: string | null;
tools: Array<Tool>;
allowDelegation: boolean;
verbose: boolean;
image: string;
image?: string | null;
};

View File

@@ -1,10 +1,23 @@
import { Task } from "./task";
import { Agent } from "./agent";
import { Task, TaskInput } from "./task";
type ProcessType = "SEQUENTIAL" | "HIERARCHICAL";
export type Mission = {
id?: number;
name: string;
crew: Array<string>;
crew: Array<Agent>;
tasks: Array<Task>;
verbose: boolean;
process: string;
result: string;
process: ProcessType;
result?: string;
};
export type CreateMissionInput = {
id?: number;
name: string;
crew: Array<number>;
tasks: Array<TaskInput>;
verbose: boolean;
process: ProcessType;
};

View File

@@ -1,5 +1,13 @@
import { Agent } from "./agent";
export type TaskInput = {
name: string;
description: string;
agent?: number;
};
export type Task = {
name: string;
description: string;
agent: string;
agent?: Agent | null;
};

5
src/utils/prisma.ts Normal file
View File

@@ -0,0 +1,5 @@
import { PrismaClient } from "@prisma/client";
const prisma: PrismaClient = new PrismaClient();
export default prisma;