mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-01-08 22:58:01 -05:00
feat(builder,server): add review of agent submissions to the admin portal (#7914)
Co-authored-by: Aarushi <aarushik93@gmail.com>
This commit is contained in:
8
.vscode/all-projects.code-workspace
vendored
8
.vscode/all-projects.code-workspace
vendored
@@ -32,6 +32,14 @@
|
||||
"name": "market",
|
||||
"path": "../rnd/market"
|
||||
},
|
||||
{
|
||||
"name": "lib",
|
||||
"path": "../rnd/autogpt_libs"
|
||||
},
|
||||
{
|
||||
"name": "infra",
|
||||
"path": "../rnd/infra"
|
||||
},
|
||||
{
|
||||
"name": "[root]",
|
||||
"path": ".."
|
||||
|
||||
18
rnd/autogpt_builder/src/app/admin/dashboard/page.tsx
Normal file
18
rnd/autogpt_builder/src/app/admin/dashboard/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import { withRoleAccess } from "@/lib/withRoleAccess";
|
||||
import React from "react";
|
||||
|
||||
function AdminDashboard() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Admin Dashboard</h1>
|
||||
{/* Add your admin-only content here */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default async function AdminDashboardPage() {
|
||||
"use server";
|
||||
const withAdminAccess = await withRoleAccess(["admin"]);
|
||||
const ProtectedAdminDashboard = await withAdminAccess(AdminDashboard);
|
||||
return <ProtectedAdminDashboard />;
|
||||
}
|
||||
100
rnd/autogpt_builder/src/app/admin/layout.tsx
Normal file
100
rnd/autogpt_builder/src/app/admin/layout.tsx
Normal file
@@ -0,0 +1,100 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { BinaryIcon, XIcon } from "lucide-react";
|
||||
import { usePathname } from "next/navigation"; // Add this import
|
||||
|
||||
const tabs = [
|
||||
{ name: "Dashboard", href: "/admin/dashboard" },
|
||||
{ name: "Marketplace", href: "/admin/marketplace" },
|
||||
{ name: "Users", href: "/admin/users" },
|
||||
{ name: "Settings", href: "/admin/settings" },
|
||||
];
|
||||
|
||||
export default function AdminLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const pathname = usePathname(); // Get the current pathname
|
||||
const [activeTab, setActiveTab] = useState(() => {
|
||||
// Set active tab based on the current route
|
||||
return tabs.find((tab) => tab.href === pathname)?.name || tabs[0].name;
|
||||
});
|
||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-100">
|
||||
<nav className="bg-white shadow-sm">
|
||||
<div className="max-w-10xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex h-16 items-center justify-between">
|
||||
<div className="flex items-center">
|
||||
<div className="flex-shrink-0">
|
||||
<h1 className="text-xl font-bold">Admin Panel</h1>
|
||||
</div>
|
||||
<div className="hidden sm:ml-6 sm:flex sm:space-x-8">
|
||||
{tabs.map((tab) => (
|
||||
<Link
|
||||
key={tab.name}
|
||||
href={tab.href}
|
||||
className={`${
|
||||
activeTab === tab.name
|
||||
? "border-indigo-500 text-indigo-600"
|
||||
: "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700"
|
||||
} inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium`}
|
||||
onClick={() => setActiveTab(tab.name)}
|
||||
>
|
||||
{tab.name}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="sm:hidden">
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-100 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500"
|
||||
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
||||
>
|
||||
<span className="sr-only">Open main menu</span>
|
||||
{mobileMenuOpen ? (
|
||||
<XIcon className="block h-6 w-6" aria-hidden="true" />
|
||||
) : (
|
||||
<BinaryIcon className="block h-6 w-6" aria-hidden="true" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{mobileMenuOpen && (
|
||||
<div className="sm:hidden">
|
||||
<div className="space-y-1 pb-3 pt-2">
|
||||
{tabs.map((tab) => (
|
||||
<Link
|
||||
key={tab.name}
|
||||
href={tab.href}
|
||||
className={`${
|
||||
activeTab === tab.name
|
||||
? "border-indigo-500 bg-indigo-50 text-indigo-700"
|
||||
: "border-transparent text-gray-600 hover:border-gray-300 hover:bg-gray-50 hover:text-gray-800"
|
||||
} block border-l-4 py-2 pl-3 pr-4 text-base font-medium`}
|
||||
onClick={() => {
|
||||
setActiveTab(tab.name);
|
||||
setMobileMenuOpen(false);
|
||||
}}
|
||||
>
|
||||
{tab.name}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</nav>
|
||||
|
||||
<main className="py-10">
|
||||
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">{children}</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
22
rnd/autogpt_builder/src/app/admin/marketplace/page.tsx
Normal file
22
rnd/autogpt_builder/src/app/admin/marketplace/page.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { withRoleAccess } from "@/lib/withRoleAccess";
|
||||
|
||||
import React from "react";
|
||||
import { getReviewableAgents } from "@/components/admin/marketplace/actions";
|
||||
import AdminMarketplaceCard from "@/components/admin/marketplace/AdminMarketplaceCard";
|
||||
import AdminMarketplaceAgentList from "@/components/admin/marketplace/AdminMarketplaceAgentList";
|
||||
async function AdminMarketplace() {
|
||||
const agents = await getReviewableAgents();
|
||||
return (
|
||||
<div>
|
||||
<h3>Agents to review</h3>
|
||||
<AdminMarketplaceAgentList agents={agents.agents} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default async function AdminDashboardPage() {
|
||||
"use server";
|
||||
const withAdminAccess = await withRoleAccess(["admin"]);
|
||||
const ProtectedAdminMarketplace = await withAdminAccess(AdminMarketplace);
|
||||
return <ProtectedAdminMarketplace />;
|
||||
}
|
||||
18
rnd/autogpt_builder/src/app/admin/settings/page.tsx
Normal file
18
rnd/autogpt_builder/src/app/admin/settings/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import { withRoleAccess } from "@/lib/withRoleAccess";
|
||||
import React from "react";
|
||||
|
||||
function AdminSettings() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Admin Settings</h1>
|
||||
{/* Add your admin-only settings content here */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default async function AdminSettingsPage() {
|
||||
"use server";
|
||||
const withAdminAccess = await withRoleAccess(["admin"]);
|
||||
const ProtectedAdminSettings = await withAdminAccess(AdminSettings);
|
||||
return <ProtectedAdminSettings />;
|
||||
}
|
||||
18
rnd/autogpt_builder/src/app/admin/users/page.tsx
Normal file
18
rnd/autogpt_builder/src/app/admin/users/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import { withRoleAccess } from "@/lib/withRoleAccess";
|
||||
import React from "react";
|
||||
|
||||
function AdminUsers() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Users Dashboard</h1>
|
||||
{/* Add your admin-only content here */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default async function AdminUsersPage() {
|
||||
"use server";
|
||||
const withAdminAccess = await withRoleAccess(["admin"]);
|
||||
const ProtectedAdminUsers = await withAdminAccess(AdminUsers);
|
||||
return <ProtectedAdminUsers />;
|
||||
}
|
||||
@@ -3,8 +3,6 @@
|
||||
import React, { useState, useEffect, useMemo } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import ReactFlow, { Background, Controls } from "reactflow";
|
||||
import "reactflow/dist/style.css";
|
||||
import MarketplaceAPI from "@/lib/marketplace-api";
|
||||
import AutoGPTServerAPI from "@/lib/autogpt-server-api";
|
||||
import { Card } from "@/components/ui/card";
|
||||
|
||||
9
rnd/autogpt_builder/src/app/unauthorized/page.tsx
Normal file
9
rnd/autogpt_builder/src/app/unauthorized/page.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
// app/unauthorized/page.tsx
|
||||
export default function Unauthorized() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Unauthorized Access</h1>
|
||||
<p>You do not have permission to view this page.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -155,40 +155,6 @@ function AgentDetailContent({ agent }: { agent: AgentDetailResponse }) {
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
<div className="border-t border-gray-200 px-4 py-5 sm:px-6">
|
||||
<button
|
||||
className="flex w-full items-center justify-between text-left text-sm font-medium text-indigo-600 hover:text-indigo-500"
|
||||
onClick={() => setIsGraphExpanded(!isGraphExpanded)}
|
||||
>
|
||||
<span>Agent Graph</span>
|
||||
{isGraphExpanded ? (
|
||||
<ChevronUp size={20} />
|
||||
) : (
|
||||
<ChevronDown size={20} />
|
||||
)}
|
||||
</button>
|
||||
{isGraphExpanded && (
|
||||
<div className="mt-4" style={{ height: "600px" }}>
|
||||
<ReactFlow
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
// nodeTypes={nodeTypes}
|
||||
// edgeTypes={edgeTypes}
|
||||
// connectionLineComponent={ConnectionLine}
|
||||
fitView
|
||||
attributionPosition="bottom-left"
|
||||
nodesConnectable={false}
|
||||
nodesDraggable={false}
|
||||
zoomOnScroll={false}
|
||||
panOnScroll={false}
|
||||
elementsSelectable={false}
|
||||
>
|
||||
<Controls showInteractive={false} />
|
||||
<Background />
|
||||
</ReactFlow>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -14,21 +14,34 @@ import useUser from "@/hooks/useUser";
|
||||
const ProfileDropdown = () => {
|
||||
const { supabase } = useSupabase();
|
||||
const router = useRouter();
|
||||
const { user, role, isLoading } = useUser();
|
||||
|
||||
if (isLoading) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" className="h-8 w-8 rounded-full">
|
||||
<Avatar>
|
||||
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
|
||||
<AvatarImage
|
||||
src={user?.user_metadata["avatar_url"]}
|
||||
alt="User Avatar"
|
||||
/>
|
||||
<AvatarFallback>CN</AvatarFallback>
|
||||
</Avatar>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuItem onClick={() => router.push("profile")}>
|
||||
<DropdownMenuItem onClick={() => router.push("/profile")}>
|
||||
Profile
|
||||
</DropdownMenuItem>
|
||||
{role === "admin" && (
|
||||
<DropdownMenuItem onClick={() => router.push("/admin/dashboard")}>
|
||||
Admin Dashboard
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<DropdownMenuItem onClick={() => supabase?.auth.signOut()}>
|
||||
Log out
|
||||
</DropdownMenuItem>
|
||||
|
||||
27
rnd/autogpt_builder/src/components/RoleBasedAccess.tsx
Normal file
27
rnd/autogpt_builder/src/components/RoleBasedAccess.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
// components/RoleBasedAccess.tsx
|
||||
import React from "react";
|
||||
import useUser from "@/hooks/useUser";
|
||||
|
||||
interface RoleBasedAccessProps {
|
||||
allowedRoles: string[];
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const RoleBasedAccess: React.FC<RoleBasedAccessProps> = ({
|
||||
allowedRoles,
|
||||
children,
|
||||
}) => {
|
||||
const { role, isLoading } = useUser();
|
||||
|
||||
if (isLoading) {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
|
||||
if (!role || !allowedRoles.includes(role)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export default RoleBasedAccess;
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Agent } from "@/lib/marketplace-api";
|
||||
import AdminMarketplaceCard from "./AdminMarketplaceCard";
|
||||
import { ClipboardX } from "lucide-react";
|
||||
|
||||
export default function AdminMarketplaceAgentList({
|
||||
agents,
|
||||
}: {
|
||||
agents: Agent[];
|
||||
}) {
|
||||
if (agents.length === 0) {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center py-12 text-gray-500">
|
||||
<ClipboardX size={48} />
|
||||
<p className="mt-4 text-lg font-semibold">No agents to review</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{agents.map((agent) => (
|
||||
<AdminMarketplaceCard agent={agent} key={agent.id} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
"use client";
|
||||
import { Card } from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import { approveAgent, rejectAgent } from "./actions";
|
||||
import { Agent } from "@/lib/marketplace-api";
|
||||
import Link from "next/link";
|
||||
import { useState } from "react";
|
||||
import { Input } from "@/components/ui/input";
|
||||
|
||||
function AdminMarketplaceCard({ agent }: { agent: Agent }) {
|
||||
const [isApproved, setIsApproved] = useState(false);
|
||||
const [isRejected, setIsRejected] = useState(false);
|
||||
const [comment, setComment] = useState("");
|
||||
|
||||
const approveAgentWithId = approveAgent.bind(
|
||||
null,
|
||||
agent.id,
|
||||
agent.version,
|
||||
comment,
|
||||
);
|
||||
const rejectAgentWithId = rejectAgent.bind(
|
||||
null,
|
||||
agent.id,
|
||||
agent.version,
|
||||
comment,
|
||||
);
|
||||
|
||||
const handleApprove = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
await approveAgentWithId();
|
||||
setIsApproved(true);
|
||||
};
|
||||
|
||||
const handleReject = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
await rejectAgentWithId();
|
||||
setIsRejected(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{!isApproved && !isRejected && (
|
||||
<Card key={agent.id} className="m-3 flex h-[300px] flex-col p-4">
|
||||
<div className="mb-2 flex items-start justify-between">
|
||||
<Link
|
||||
href={`/marketplace/${agent.id}`}
|
||||
className="text-lg font-semibold hover:underline"
|
||||
>
|
||||
{agent.name}
|
||||
</Link>
|
||||
<Badge variant="outline">v{agent.version}</Badge>
|
||||
</div>
|
||||
<p className="mb-2 text-sm text-gray-500">by {agent.author}</p>
|
||||
<ScrollArea className="flex-grow">
|
||||
<p className="mb-2 text-sm text-gray-600">{agent.description}</p>
|
||||
<div className="mb-2 flex flex-wrap gap-1">
|
||||
{agent.categories.map((category) => (
|
||||
<Badge key={category} variant="secondary">
|
||||
{category}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{agent.keywords.map((keyword) => (
|
||||
<Badge key={keyword} variant="outline">
|
||||
{keyword}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
</ScrollArea>
|
||||
<div className="mb-2 flex justify-between text-xs text-gray-500">
|
||||
<span>
|
||||
Created: {new Date(agent.createdAt).toLocaleDateString()}
|
||||
</span>
|
||||
<span>
|
||||
Updated: {new Date(agent.updatedAt).toLocaleDateString()}
|
||||
</span>
|
||||
</div>
|
||||
<div className="mb-4 flex justify-between text-sm">
|
||||
<span>👁 {agent.views}</span>
|
||||
<span>⬇️ {agent.downloads}</span>
|
||||
</div>
|
||||
<div className="mt-auto space-y-2">
|
||||
<div className="flex justify-end space-x-2">
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Add a comment (optional)"
|
||||
value={comment}
|
||||
onChange={(e) => setComment(e.target.value)}
|
||||
/>
|
||||
{!isRejected && (
|
||||
<form onSubmit={handleReject}>
|
||||
<Button variant="outline" type="submit">
|
||||
Reject
|
||||
</Button>
|
||||
</form>
|
||||
)}
|
||||
{!isApproved && (
|
||||
<form onSubmit={handleApprove}>
|
||||
<Button type="submit">Approve</Button>
|
||||
</form>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default AdminMarketplaceCard;
|
||||
@@ -0,0 +1,27 @@
|
||||
"use server";
|
||||
import MarketplaceAPI from "@/lib/marketplace-api";
|
||||
|
||||
export async function approveAgent(
|
||||
agentId: string,
|
||||
version: number,
|
||||
comment: string,
|
||||
) {
|
||||
const api = new MarketplaceAPI();
|
||||
await api.approveAgentSubmission(agentId, version, comment);
|
||||
console.debug(`Approving agent ${agentId}`);
|
||||
}
|
||||
|
||||
export async function rejectAgent(
|
||||
agentId: string,
|
||||
version: number,
|
||||
comment: string,
|
||||
) {
|
||||
const api = new MarketplaceAPI();
|
||||
await api.rejectAgentSubmission(agentId, version, comment);
|
||||
console.debug(`Rejecting agent ${agentId}`);
|
||||
}
|
||||
|
||||
export async function getReviewableAgents() {
|
||||
const api = new MarketplaceAPI();
|
||||
return api.getAgentSubmissions();
|
||||
}
|
||||
@@ -8,13 +8,26 @@ const getServerUser = async () => {
|
||||
}
|
||||
|
||||
try {
|
||||
const { data, error } = await supabase.auth.getUser();
|
||||
const {
|
||||
data: { user },
|
||||
error,
|
||||
} = await supabase.auth.getUser();
|
||||
if (error) {
|
||||
return { user: null, error: error.message };
|
||||
console.error("Supabase auth error:", error);
|
||||
return { user: null, role: null, error: `Auth error: ${error.message}` };
|
||||
}
|
||||
return { user: data.user, error: null };
|
||||
if (!user) {
|
||||
return { user: null, role: null, error: "No user found in the response" };
|
||||
}
|
||||
const role = user.role || null;
|
||||
return { user, role, error: null };
|
||||
} catch (error) {
|
||||
return { user: null, error: (error as Error).message };
|
||||
console.error("Unexpected error in getServerUser:", error);
|
||||
return {
|
||||
user: null,
|
||||
role: null,
|
||||
error: `Unexpected error: ${(error as Error).message}`,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ const useUser = () => {
|
||||
const [session, setSession] = useState<Session | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [role, setRole] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (isSupabaseLoading || !supabase) {
|
||||
@@ -19,16 +20,21 @@ const useUser = () => {
|
||||
const fetchUser = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const {
|
||||
data: { user },
|
||||
} = await supabase.auth.getUser();
|
||||
const {
|
||||
data: { session },
|
||||
} = await supabase.auth.getSession();
|
||||
setUser(user);
|
||||
setSession(session);
|
||||
const { data: userData, error: userError } =
|
||||
await supabase.auth.getUser();
|
||||
const { data: sessionData, error: sessionError } =
|
||||
await supabase.auth.getSession();
|
||||
|
||||
if (userError) throw new Error(`User error: ${userError.message}`);
|
||||
if (sessionError)
|
||||
throw new Error(`Session error: ${sessionError.message}`);
|
||||
|
||||
setUser(userData.user);
|
||||
setSession(sessionData.session);
|
||||
setRole(userData.user?.role || null);
|
||||
} catch (e) {
|
||||
setError("Failed to fetch user data");
|
||||
setError(e instanceof Error ? e.message : "Failed to fetch user data");
|
||||
console.error("Error in useUser hook:", e);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
@@ -41,13 +47,21 @@ const useUser = () => {
|
||||
} = supabase.auth.onAuthStateChange((_event, session) => {
|
||||
setSession(session);
|
||||
setUser(session?.user ?? null);
|
||||
setRole(session?.user?.role || null);
|
||||
|
||||
setIsLoading(false);
|
||||
});
|
||||
|
||||
return () => subscription.unsubscribe();
|
||||
}, [supabase, isSupabaseLoading]);
|
||||
|
||||
return { user, session, isLoading: isLoading || isSupabaseLoading, error };
|
||||
return {
|
||||
user,
|
||||
session,
|
||||
role,
|
||||
isLoading: isLoading || isSupabaseLoading,
|
||||
error,
|
||||
};
|
||||
};
|
||||
|
||||
export default useUser;
|
||||
|
||||
@@ -121,10 +121,40 @@ export default class MarketplaceAPI {
|
||||
);
|
||||
}
|
||||
|
||||
async getAgentSubmissions(): Promise<AgentListResponse> {
|
||||
return this._get("/admin/agent/submissions");
|
||||
}
|
||||
|
||||
async createAgentEntry(request: AddAgentRequest): Promise<AgentResponse> {
|
||||
return this._post("/admin/agent", request);
|
||||
}
|
||||
|
||||
async approveAgentSubmission(
|
||||
agentId: string,
|
||||
version: number,
|
||||
comments: string = "",
|
||||
): Promise<AgentResponse> {
|
||||
return this._post("/admin/agent/submissions", {
|
||||
agent_id: agentId,
|
||||
version: version,
|
||||
status: "APPROVED",
|
||||
comments: comments,
|
||||
});
|
||||
}
|
||||
|
||||
async rejectAgentSubmission(
|
||||
agentId: string,
|
||||
version: number,
|
||||
comments: string = "",
|
||||
): Promise<AgentResponse> {
|
||||
return this._post("/admin/agent/submissions", {
|
||||
agent_id: agentId,
|
||||
version: version,
|
||||
status: "REJECTED",
|
||||
comments: comments,
|
||||
});
|
||||
}
|
||||
|
||||
private async _get(path: string) {
|
||||
return this._request("GET", path);
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ export async function updateSession(request: NextRequest) {
|
||||
|
||||
const {
|
||||
data: { user },
|
||||
error,
|
||||
} = await supabase.auth.getUser();
|
||||
|
||||
if (
|
||||
|
||||
16
rnd/autogpt_builder/src/lib/withRoleAccess.ts
Normal file
16
rnd/autogpt_builder/src/lib/withRoleAccess.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { redirect } from "next/navigation";
|
||||
import getServerUser from "@/hooks/getServerUser";
|
||||
import React from "react";
|
||||
|
||||
export async function withRoleAccess(allowedRoles: string[]) {
|
||||
"use server";
|
||||
return async function <T extends React.ComponentType<any>>(Component: T) {
|
||||
const { user, role, error } = await getServerUser();
|
||||
|
||||
if (error || !user || !role || !allowedRoles.includes(role)) {
|
||||
redirect("/unauthorized");
|
||||
}
|
||||
|
||||
return Component;
|
||||
};
|
||||
}
|
||||
@@ -153,6 +153,46 @@
|
||||
dependencies:
|
||||
glob "10.3.10"
|
||||
|
||||
"@next/swc-darwin-arm64@14.2.4":
|
||||
version "14.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.4.tgz#da9f04c34a3d5f0b8401ed745768420e4a604036"
|
||||
integrity sha512-AH3mO4JlFUqsYcwFUHb1wAKlebHU/Hv2u2kb1pAuRanDZ7pD/A/KPD98RHZmwsJpdHQwfEc/06mgpSzwrJYnNg==
|
||||
|
||||
"@next/swc-darwin-x64@14.2.4":
|
||||
version "14.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.4.tgz#46dedb29ec5503bf171a72a3ecb8aac6e738e9d6"
|
||||
integrity sha512-QVadW73sWIO6E2VroyUjuAxhWLZWEpiFqHdZdoQ/AMpN9YWGuHV8t2rChr0ahy+irKX5mlDU7OY68k3n4tAZTg==
|
||||
|
||||
"@next/swc-linux-arm64-gnu@14.2.4":
|
||||
version "14.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.4.tgz#c9697ab9eb422bd1d7ffd0eb0779cc2aefa9d4a1"
|
||||
integrity sha512-KT6GUrb3oyCfcfJ+WliXuJnD6pCpZiosx2X3k66HLR+DMoilRb76LpWPGb4tZprawTtcnyrv75ElD6VncVamUQ==
|
||||
|
||||
"@next/swc-linux-arm64-musl@14.2.4":
|
||||
version "14.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.4.tgz#cbbceb2008571c743b5a310a488d2e166d200a75"
|
||||
integrity sha512-Alv8/XGSs/ytwQcbCHwze1HmiIkIVhDHYLjczSVrf0Wi2MvKn/blt7+S6FJitj3yTlMwMxII1gIJ9WepI4aZ/A==
|
||||
|
||||
"@next/swc-linux-x64-gnu@14.2.4":
|
||||
version "14.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.4.tgz#d79184223f857bacffb92f643cb2943a43632568"
|
||||
integrity sha512-ze0ShQDBPCqxLImzw4sCdfnB3lRmN3qGMB2GWDRlq5Wqy4G36pxtNOo2usu/Nm9+V2Rh/QQnrRc2l94kYFXO6Q==
|
||||
|
||||
"@next/swc-linux-x64-musl@14.2.4":
|
||||
version "14.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.4.tgz#6b6c3e5ac02ca5e63394d280ec8ee607491902df"
|
||||
integrity sha512-8dwC0UJoc6fC7PX70csdaznVMNr16hQrTDAMPvLPloazlcaWfdPogq+UpZX6Drqb1OBlwowz8iG7WR0Tzk/diQ==
|
||||
|
||||
"@next/swc-win32-arm64-msvc@14.2.4":
|
||||
version "14.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.4.tgz#dbad3906e870dba84c5883d9d4c4838472e0697f"
|
||||
integrity sha512-jxyg67NbEWkDyvM+O8UDbPAyYRZqGLQDTPwvrBBeOSyVWW/jFQkQKQ70JDqDSYg1ZDdl+E3nkbFbq8xM8E9x8A==
|
||||
|
||||
"@next/swc-win32-ia32-msvc@14.2.4":
|
||||
version "14.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.4.tgz#6074529b91ba49132922ce89a2e16d25d2ec235d"
|
||||
integrity sha512-twrmN753hjXRdcrZmZttb/m5xaCBFa48Dt3FbeEItpJArxriYDunWxJn+QFXdJ3hPkm4u7CKxncVvnmgQMY1ag==
|
||||
|
||||
"@next/swc-win32-x64-msvc@14.2.4":
|
||||
version "14.2.4"
|
||||
resolved "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.4.tgz"
|
||||
@@ -173,7 +213,7 @@
|
||||
"@nodelib/fs.stat" "2.0.5"
|
||||
run-parallel "^1.1.9"
|
||||
|
||||
"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5":
|
||||
"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
|
||||
version "2.0.5"
|
||||
resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz"
|
||||
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
|
||||
@@ -287,26 +327,6 @@
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz"
|
||||
integrity sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==
|
||||
|
||||
"@radix-ui/react-dialog@^1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.1.tgz"
|
||||
integrity sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg==
|
||||
dependencies:
|
||||
"@radix-ui/primitive" "1.1.0"
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
"@radix-ui/react-context" "1.1.0"
|
||||
"@radix-ui/react-dismissable-layer" "1.1.0"
|
||||
"@radix-ui/react-focus-guards" "1.1.0"
|
||||
"@radix-ui/react-focus-scope" "1.1.0"
|
||||
"@radix-ui/react-id" "1.1.0"
|
||||
"@radix-ui/react-portal" "1.1.1"
|
||||
"@radix-ui/react-presence" "1.1.0"
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-slot" "1.1.0"
|
||||
"@radix-ui/react-use-controllable-state" "1.1.0"
|
||||
aria-hidden "^1.1.1"
|
||||
react-remove-scroll "2.5.7"
|
||||
|
||||
"@radix-ui/react-dialog@1.0.5":
|
||||
version "1.0.5"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz"
|
||||
@@ -328,6 +348,26 @@
|
||||
aria-hidden "^1.1.1"
|
||||
react-remove-scroll "2.5.5"
|
||||
|
||||
"@radix-ui/react-dialog@^1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.1.tgz"
|
||||
integrity sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg==
|
||||
dependencies:
|
||||
"@radix-ui/primitive" "1.1.0"
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
"@radix-ui/react-context" "1.1.0"
|
||||
"@radix-ui/react-dismissable-layer" "1.1.0"
|
||||
"@radix-ui/react-focus-guards" "1.1.0"
|
||||
"@radix-ui/react-focus-scope" "1.1.0"
|
||||
"@radix-ui/react-id" "1.1.0"
|
||||
"@radix-ui/react-portal" "1.1.1"
|
||||
"@radix-ui/react-presence" "1.1.0"
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-slot" "1.1.0"
|
||||
"@radix-ui/react-use-controllable-state" "1.1.0"
|
||||
aria-hidden "^1.1.1"
|
||||
react-remove-scroll "2.5.7"
|
||||
|
||||
"@radix-ui/react-direction@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz"
|
||||
@@ -600,13 +640,6 @@
|
||||
dependencies:
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
|
||||
"@radix-ui/react-slot@^1.1.0", "@radix-ui/react-slot@1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz"
|
||||
integrity sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==
|
||||
dependencies:
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
|
||||
"@radix-ui/react-slot@1.0.2":
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz"
|
||||
@@ -615,6 +648,13 @@
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/react-compose-refs" "1.0.1"
|
||||
|
||||
"@radix-ui/react-slot@1.1.0", "@radix-ui/react-slot@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz"
|
||||
integrity sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==
|
||||
dependencies:
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
|
||||
"@radix-ui/react-switch@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.1.0.tgz"
|
||||
@@ -731,6 +771,11 @@
|
||||
resolved "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz"
|
||||
integrity sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==
|
||||
|
||||
"@rollup/rollup-linux-x64-gnu@^4.9.5":
|
||||
version "4.21.1"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.1.tgz#790ae96118cc892464e9f10da358c0c8a6b9acdd"
|
||||
integrity sha512-kXQVcWqDcDKw0S2E0TmhlTLlUgAmMVqPrJZR+KpH/1ZaZhLSl23GZpQVmawBQGVhyP5WXIsIQ/zqbDBBYmxm5w==
|
||||
|
||||
"@rushstack/eslint-patch@^1.3.3":
|
||||
version "1.10.4"
|
||||
resolved "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz"
|
||||
@@ -755,7 +800,7 @@
|
||||
dependencies:
|
||||
"@supabase/node-fetch" "^2.6.14"
|
||||
|
||||
"@supabase/node-fetch@^2.6.14", "@supabase/node-fetch@2.6.15":
|
||||
"@supabase/node-fetch@2.6.15", "@supabase/node-fetch@^2.6.14":
|
||||
version "2.6.15"
|
||||
resolved "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz"
|
||||
integrity sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==
|
||||
@@ -795,7 +840,7 @@
|
||||
dependencies:
|
||||
"@supabase/node-fetch" "^2.6.14"
|
||||
|
||||
"@supabase/supabase-js@^2.43.4", "@supabase/supabase-js@^2.45.0":
|
||||
"@supabase/supabase-js@^2.45.0":
|
||||
version "2.45.1"
|
||||
resolved "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.45.1.tgz"
|
||||
integrity sha512-/PVe3lXmalazD8BGMIoI7+ttvT1mLXy13lNcoAPtjP1TDDY83g8csZbVR6l+0/RZtvJxl3LGXfTJT4bjWgC5Nw==
|
||||
@@ -958,7 +1003,7 @@
|
||||
resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz"
|
||||
integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==
|
||||
|
||||
"@types/react-dom@*", "@types/react-dom@^18":
|
||||
"@types/react-dom@^18":
|
||||
version "18.3.0"
|
||||
resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz"
|
||||
integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==
|
||||
@@ -972,7 +1017,7 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^16.9.0 || ^17.0.0 || ^18.0.0", "@types/react@^18", "@types/react@>=16.8", "@types/react@>=18":
|
||||
"@types/react@*", "@types/react@^18":
|
||||
version "18.3.4"
|
||||
resolved "https://registry.npmjs.org/@types/react/-/react-18.3.4.tgz"
|
||||
integrity sha512-J7W30FTdfCxDDjmfRM+/JqLHBIyl7xUIp9kwK637FGmY7+mkSFSe6L4jpZzhj5QMfLssSDP4/i75AKkrdC7/Jw==
|
||||
@@ -1075,7 +1120,7 @@ acorn-jsx@^5.3.2:
|
||||
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
|
||||
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
||||
|
||||
"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.9.0:
|
||||
acorn@^8.9.0:
|
||||
version "8.12.1"
|
||||
resolved "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz"
|
||||
integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==
|
||||
@@ -1412,16 +1457,16 @@ client-only@0.0.1:
|
||||
resolved "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz"
|
||||
integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
|
||||
|
||||
clsx@^2.0.0, clsx@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz"
|
||||
integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
|
||||
|
||||
clsx@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz"
|
||||
integrity sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==
|
||||
|
||||
clsx@^2.0.0, clsx@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz"
|
||||
integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
|
||||
|
||||
cmdk@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/cmdk/-/cmdk-1.0.0.tgz"
|
||||
@@ -1481,7 +1526,7 @@ csstype@^3.0.2:
|
||||
resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz"
|
||||
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
|
||||
|
||||
d3-array@^3.1.6, "d3-array@2 - 3", "d3-array@2.10.0 - 3":
|
||||
"d3-array@2 - 3", "d3-array@2.10.0 - 3", d3-array@^3.1.6:
|
||||
version "3.2.4"
|
||||
resolved "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz"
|
||||
integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==
|
||||
@@ -1498,7 +1543,7 @@ d3-array@^3.1.6, "d3-array@2 - 3", "d3-array@2.10.0 - 3":
|
||||
resolved "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz"
|
||||
integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==
|
||||
|
||||
d3-drag@^3.0.0, "d3-drag@2 - 3":
|
||||
"d3-drag@2 - 3", d3-drag@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz"
|
||||
integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==
|
||||
@@ -1506,7 +1551,7 @@ d3-drag@^3.0.0, "d3-drag@2 - 3":
|
||||
d3-dispatch "1 - 3"
|
||||
d3-selection "3"
|
||||
|
||||
d3-ease@^3.0.1, "d3-ease@1 - 3":
|
||||
"d3-ease@1 - 3", d3-ease@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz"
|
||||
integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==
|
||||
@@ -1516,7 +1561,7 @@ d3-ease@^3.0.1, "d3-ease@1 - 3":
|
||||
resolved "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz"
|
||||
integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==
|
||||
|
||||
d3-interpolate@^3.0.1, "d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3":
|
||||
"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz"
|
||||
integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==
|
||||
@@ -1539,7 +1584,7 @@ d3-scale@^4.0.2:
|
||||
d3-time "2.1.1 - 3"
|
||||
d3-time-format "2 - 4"
|
||||
|
||||
d3-selection@^3.0.0, "d3-selection@2 - 3", d3-selection@3:
|
||||
"d3-selection@2 - 3", d3-selection@3, d3-selection@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz"
|
||||
integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==
|
||||
@@ -1558,14 +1603,14 @@ d3-shape@^3.1.0:
|
||||
dependencies:
|
||||
d3-time "1 - 3"
|
||||
|
||||
d3-time@^3.0.0, "d3-time@1 - 3", "d3-time@2.1.1 - 3":
|
||||
"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz"
|
||||
integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==
|
||||
dependencies:
|
||||
d3-array "2 - 3"
|
||||
|
||||
d3-timer@^3.0.1, "d3-timer@1 - 3":
|
||||
"d3-timer@1 - 3", d3-timer@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz"
|
||||
integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==
|
||||
@@ -1624,7 +1669,7 @@ data-view-byte-offset@^1.0.0:
|
||||
es-errors "^1.3.0"
|
||||
is-data-view "^1.0.1"
|
||||
|
||||
"date-fns@^2.28.0 || ^3.0.0", date-fns@^3.6.0:
|
||||
date-fns@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz"
|
||||
integrity sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==
|
||||
@@ -1971,7 +2016,7 @@ eslint-module-utils@^2.7.4, eslint-module-utils@^2.8.0:
|
||||
dependencies:
|
||||
debug "^3.2.7"
|
||||
|
||||
eslint-plugin-import@*, eslint-plugin-import@^2.28.1:
|
||||
eslint-plugin-import@^2.28.1:
|
||||
version "2.29.1"
|
||||
resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz"
|
||||
integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==
|
||||
@@ -2058,7 +2103,7 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4
|
||||
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz"
|
||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||
|
||||
eslint@*, "eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7", "eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^7.23.0 || ^8.0.0", eslint@^8, eslint@^8.56.0:
|
||||
eslint@^8:
|
||||
version "8.57.0"
|
||||
resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz"
|
||||
integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==
|
||||
@@ -2254,6 +2299,11 @@ fs.realpath@^1.0.0:
|
||||
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||
|
||||
fsevents@~2.3.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
||||
|
||||
function-bind@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"
|
||||
@@ -2306,7 +2356,7 @@ get-tsconfig@^4.5.0:
|
||||
dependencies:
|
||||
resolve-pkg-maps "^1.0.0"
|
||||
|
||||
glob-parent@^5.1.2:
|
||||
glob-parent@^5.1.2, glob-parent@~5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz"
|
||||
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
|
||||
@@ -2320,14 +2370,7 @@ glob-parent@^6.0.2:
|
||||
dependencies:
|
||||
is-glob "^4.0.3"
|
||||
|
||||
glob-parent@~5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz"
|
||||
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
|
||||
dependencies:
|
||||
is-glob "^4.0.1"
|
||||
|
||||
glob@^10.3.10, glob@10.3.10:
|
||||
glob@10.3.10, glob@^10.3.10:
|
||||
version "10.3.10"
|
||||
resolved "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz"
|
||||
integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==
|
||||
@@ -3220,6 +3263,13 @@ micromatch@^4.0.4, micromatch@^4.0.5:
|
||||
braces "^3.0.3"
|
||||
picomatch "^2.3.1"
|
||||
|
||||
minimatch@9.0.3:
|
||||
version "9.0.3"
|
||||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz"
|
||||
integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz"
|
||||
@@ -3234,13 +3284,6 @@ minimatch@^9.0.1:
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@9.0.3:
|
||||
version "9.0.3"
|
||||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz"
|
||||
integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimist@^1.2.0, minimist@^1.2.6:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz"
|
||||
@@ -3256,7 +3299,7 @@ moment@^2.30.1:
|
||||
resolved "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz"
|
||||
integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==
|
||||
|
||||
ms@^2.1.1, ms@2.1.2:
|
||||
ms@2.1.2, ms@^2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
@@ -3285,7 +3328,7 @@ next-themes@^0.3.0:
|
||||
resolved "https://registry.npmjs.org/next-themes/-/next-themes-0.3.0.tgz"
|
||||
integrity sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w==
|
||||
|
||||
"next@^13.0.0 || ^14.0.0", next@14.2.4:
|
||||
next@14.2.4:
|
||||
version "14.2.4"
|
||||
resolved "https://registry.npmjs.org/next/-/next-14.2.4.tgz"
|
||||
integrity sha512-R8/V7vugY+822rsQGQCjoLhMuC9oFj9SOi4Cl4b2wjDrseD0LRZ10W7R6Czo4w9ZznVSshKjuIomsRjvm9EKJQ==
|
||||
@@ -3544,15 +3587,6 @@ postcss-value-parser@^4.0.0:
|
||||
resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz"
|
||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||
|
||||
postcss@^8, postcss@^8.0.0, postcss@^8.2.14, postcss@^8.4.21, postcss@^8.4.23, postcss@>=8.0.9:
|
||||
version "8.4.41"
|
||||
resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz"
|
||||
integrity sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==
|
||||
dependencies:
|
||||
nanoid "^3.3.7"
|
||||
picocolors "^1.0.1"
|
||||
source-map-js "^1.2.0"
|
||||
|
||||
postcss@8.4.31:
|
||||
version "8.4.31"
|
||||
resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz"
|
||||
@@ -3562,6 +3596,15 @@ postcss@8.4.31:
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.2"
|
||||
|
||||
postcss@^8, postcss@^8.4.23:
|
||||
version "8.4.41"
|
||||
resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz"
|
||||
integrity sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==
|
||||
dependencies:
|
||||
nanoid "^3.3.7"
|
||||
picocolors "^1.0.1"
|
||||
source-map-js "^1.2.0"
|
||||
|
||||
prelude-ls@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz"
|
||||
@@ -3572,7 +3615,7 @@ prettier-plugin-tailwindcss@^0.6.6:
|
||||
resolved "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.6.tgz"
|
||||
integrity sha512-OPva5S7WAsPLEsOuOWXATi13QrCKACCiIonFgIR6V4lYv4QLp++UXVhZSzRbZxXGimkQtQT86CC6fQqTOybGng==
|
||||
|
||||
prettier@^3.0, prettier@^3.3.3:
|
||||
prettier@^3.3.3:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz"
|
||||
integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==
|
||||
@@ -3606,7 +3649,7 @@ react-day-picker@^8.10.1:
|
||||
resolved "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz"
|
||||
integrity sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==
|
||||
|
||||
"react-dom@^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18", "react-dom@^16.0.0 || ^17.0.0 || ^18.0.0", "react-dom@^16.8 || ^17 || ^18", "react-dom@^16.8 || ^17.0 || ^18.0", "react-dom@^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0", react-dom@^18, react-dom@^18.0.0, react-dom@^18.2.0, react-dom@>=16.6.0, react-dom@>=16.8.0, react-dom@>=17:
|
||||
react-dom@^18:
|
||||
version "18.3.1"
|
||||
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz"
|
||||
integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==
|
||||
@@ -3614,7 +3657,7 @@ react-day-picker@^8.10.1:
|
||||
loose-envify "^1.1.0"
|
||||
scheduler "^0.23.2"
|
||||
|
||||
react-hook-form@^7.0.0, react-hook-form@^7.52.1:
|
||||
react-hook-form@^7.52.1:
|
||||
version "7.52.2"
|
||||
resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.52.2.tgz"
|
||||
integrity sha512-pqfPEbERnxxiNMPd0bzmt1tuaPcVccywFDpyk2uV5xCIBphHV5T8SVnX9/o3kplPE1zzKt77+YIoq+EMwJp56A==
|
||||
@@ -3725,7 +3768,7 @@ react-transition-group@^4.4.5:
|
||||
loose-envify "^1.4.0"
|
||||
prop-types "^15.6.2"
|
||||
|
||||
react@*, "react@^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18", "react@^16.0.0 || ^17.0.0 || ^18.0.0", "react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8 || ^17 || ^18", "react@^16.8 || ^17.0 || ^18.0", "react@^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react@^16.8.0 || ^17 || ^18 || ^19", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.x || ^17.x || ^18.x", react@^18, react@^18.0.0, react@^18.2.0, react@^18.3.1, "react@>= 16.8.0 || 17.x.x || ^18.0.0-0", react@>=16.6.0, react@>=16.8, react@>=16.8.0, react@>=17, react@>=18:
|
||||
react@^18:
|
||||
version "18.3.1"
|
||||
resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz"
|
||||
integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
|
||||
@@ -3989,16 +4032,8 @@ streamsearch@^1.1.0:
|
||||
resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz"
|
||||
integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
|
||||
|
||||
"string-width-cjs@npm:string-width@^4.2.0":
|
||||
version "4.2.3"
|
||||
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
dependencies:
|
||||
emoji-regex "^8.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
string-width@^4.1.0:
|
||||
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0:
|
||||
name string-width-cjs
|
||||
version "4.2.3"
|
||||
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
@@ -4086,14 +4121,7 @@ stringify-entities@^4.0.0:
|
||||
character-entities-html4 "^2.0.0"
|
||||
character-entities-legacy "^3.0.0"
|
||||
|
||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
||||
version "6.0.1"
|
||||
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||
dependencies:
|
||||
ansi-regex "^5.0.1"
|
||||
|
||||
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||
@@ -4166,7 +4194,7 @@ tailwindcss-animate@^1.0.7:
|
||||
resolved "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz"
|
||||
integrity sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==
|
||||
|
||||
tailwindcss@^3.4.1, "tailwindcss@>=3.0.0 || insiders":
|
||||
tailwindcss@^3.4.1:
|
||||
version "3.4.10"
|
||||
resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.10.tgz"
|
||||
integrity sha512-KWZkVPm7yJRhdu4SRSl9d4AK2wM3a50UsvgHZO7xY77NQr2V+fIrEuoDGQcbvswWvFGbS2f6e+jC/6WJm1Dl0w==
|
||||
@@ -4331,7 +4359,7 @@ typed-array-length@^1.0.6:
|
||||
is-typed-array "^1.1.13"
|
||||
possible-typed-array-names "^1.0.0"
|
||||
|
||||
typescript@^5, typescript@^5.0.0, typescript@>=3.3.1, typescript@>=4.2.0:
|
||||
typescript@^5:
|
||||
version "5.5.4"
|
||||
resolved "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz"
|
||||
integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==
|
||||
|
||||
@@ -12,6 +12,7 @@ security = HTTPBearer()
|
||||
async def auth_middleware(request: Request):
|
||||
if not settings.ENABLE_AUTH:
|
||||
# If authentication is disabled, allow the request to proceed
|
||||
logging.warn("Auth disabled")
|
||||
return {}
|
||||
|
||||
security = HTTPBearer()
|
||||
|
||||
@@ -109,7 +109,7 @@ async def update_agent_entry(
|
||||
version: int,
|
||||
submission_state: prisma.enums.SubmissionStatus,
|
||||
comments: str | None = None,
|
||||
):
|
||||
) -> prisma.models.Agents | None:
|
||||
"""
|
||||
Update an existing agent entry in the database.
|
||||
|
||||
@@ -275,6 +275,7 @@ async def search_db(
|
||||
description_threshold: int = 60,
|
||||
sort_by: str = "rank",
|
||||
sort_order: typing.Literal["desc"] | typing.Literal["asc"] = "desc",
|
||||
submission_status: prisma.enums.SubmissionStatus = prisma.enums.SubmissionStatus.APPROVED,
|
||||
) -> typing.List[market.utils.extension_types.AgentsWithRank]:
|
||||
"""Perform a search for agents based on the provided query string.
|
||||
|
||||
@@ -310,6 +311,8 @@ async def search_db(
|
||||
else:
|
||||
order_by_clause = 'rank DESC, "createdAt" DESC'
|
||||
|
||||
submission_status_filter = f""""submissionStatus" = '{submission_status}'"""
|
||||
|
||||
sql_query = f"""
|
||||
WITH query AS (
|
||||
SELECT to_tsquery(string_agg(lexeme || ':*', ' & ' ORDER BY positions)) AS q
|
||||
@@ -326,9 +329,11 @@ async def search_db(
|
||||
keywords,
|
||||
categories,
|
||||
graph,
|
||||
"submissionStatus",
|
||||
"submissionDate",
|
||||
ts_rank(CAST(search AS tsvector), query.q) AS rank
|
||||
FROM "Agents", query
|
||||
WHERE 1=1 {category_filter}
|
||||
WHERE 1=1 {category_filter} AND {submission_status_filter}
|
||||
ORDER BY {order_by_clause}
|
||||
LIMIT {page_size}
|
||||
OFFSET {offset};
|
||||
@@ -397,7 +402,7 @@ async def get_top_agents_by_downloads(
|
||||
|
||||
|
||||
async def set_agent_featured(
|
||||
agent_id: str, is_featured: bool = True, category: str = "featured"
|
||||
agent_id: str, is_active: bool = True, featured_categories: list[str] = ["featured"]
|
||||
):
|
||||
"""Set an agent as featured in the database.
|
||||
|
||||
@@ -416,10 +421,13 @@ async def set_agent_featured(
|
||||
await prisma.models.FeaturedAgent.prisma().upsert(
|
||||
where={"agentId": agent_id},
|
||||
data={
|
||||
"update": {"category": category, "is_featured": is_featured},
|
||||
"update": {
|
||||
"featuredCategories": featured_categories,
|
||||
"isActive": is_active,
|
||||
},
|
||||
"create": {
|
||||
"category": category,
|
||||
"is_featured": is_featured,
|
||||
"featuredCategories": featured_categories,
|
||||
"isActive": is_active,
|
||||
"agent": {"connect": {"id": agent_id}},
|
||||
},
|
||||
},
|
||||
@@ -451,7 +459,10 @@ async def get_featured_agents(
|
||||
# Execute the query
|
||||
try:
|
||||
featured_agents = await prisma.models.FeaturedAgent.prisma().find_many(
|
||||
where={"category": category, "is_featured": True},
|
||||
where={
|
||||
"featuredCategories": {"has": category},
|
||||
"isActive": True,
|
||||
},
|
||||
include={"agent": {"include": {"AnalyticsTracker": True}}},
|
||||
skip=skip,
|
||||
take=page_size,
|
||||
@@ -478,3 +489,67 @@ async def get_featured_agents(
|
||||
except Exception as e:
|
||||
# Catch any other unexpected exceptions
|
||||
raise AgentQueryError(f"Unexpected error occurred: {str(e)}") from e
|
||||
|
||||
|
||||
async def remove_featured_category(
|
||||
agent_id: str, category: str
|
||||
) -> prisma.models.FeaturedAgent | None:
|
||||
"""Adds a featured category to an agent.
|
||||
|
||||
Args:
|
||||
agent_id (str): The ID of the agent.
|
||||
category (str): The category to add to the agent.
|
||||
|
||||
Returns:
|
||||
FeaturedAgentResponse: The updated list of featured agents.
|
||||
"""
|
||||
try:
|
||||
# get the existing categories
|
||||
featured_agent = await prisma.models.FeaturedAgent.prisma().find_unique(
|
||||
where={"agentId": agent_id},
|
||||
include={"agent": True},
|
||||
)
|
||||
|
||||
if not featured_agent:
|
||||
raise AgentQueryError(f"Agent with ID {agent_id} not found.")
|
||||
|
||||
# remove the category from the list
|
||||
featured_agent.featuredCategories.remove(category)
|
||||
|
||||
featured_agent = await prisma.models.FeaturedAgent.prisma().update(
|
||||
where={"agentId": agent_id},
|
||||
data={"featuredCategories": featured_agent.featuredCategories},
|
||||
)
|
||||
|
||||
return featured_agent
|
||||
|
||||
except prisma.errors.PrismaError as e:
|
||||
raise AgentQueryError(f"Database query failed: {str(e)}")
|
||||
except Exception as e:
|
||||
raise AgentQueryError(f"Unexpected error occurred: {str(e)}")
|
||||
|
||||
|
||||
async def add_featured_category(
|
||||
agent_id: str, category: str
|
||||
) -> prisma.models.FeaturedAgent | None:
|
||||
"""Removes a featured category from an agent.
|
||||
|
||||
Args:
|
||||
agent_id (str): The ID of the agent.
|
||||
category (str): The category to remove from the agent.
|
||||
|
||||
Returns:
|
||||
FeaturedAgentResponse: The updated list of featured agents.
|
||||
"""
|
||||
try:
|
||||
featured_agent = await prisma.models.FeaturedAgent.prisma().update(
|
||||
where={"agentId": agent_id},
|
||||
data={"featuredCategories": {"push": [category]}},
|
||||
)
|
||||
|
||||
return featured_agent
|
||||
|
||||
except prisma.errors.PrismaError as e:
|
||||
raise AgentQueryError(f"Database query failed: {str(e)}")
|
||||
except Exception as e:
|
||||
raise AgentQueryError(f"Unexpected error occurred: {str(e)}")
|
||||
|
||||
@@ -44,7 +44,7 @@ class AgentResponse(pydantic.BaseModel):
|
||||
version: int
|
||||
createdAt: datetime.datetime
|
||||
updatedAt: datetime.datetime
|
||||
submission_status: str
|
||||
submissionStatus: str
|
||||
views: int = 0
|
||||
downloads: int = 0
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ async def create_agent_entry(
|
||||
@router.post("/agent/featured/{agent_id}")
|
||||
async def set_agent_featured(
|
||||
agent_id: str,
|
||||
category: str = "featured",
|
||||
category: list[str] = ["featured"],
|
||||
user: autogpt_libs.auth.User = fastapi.Depends(
|
||||
autogpt_libs.auth.requires_admin_user
|
||||
),
|
||||
@@ -56,7 +56,7 @@ async def set_agent_featured(
|
||||
"""
|
||||
try:
|
||||
await market.db.set_agent_featured(
|
||||
agent_id, is_featured=True, category=category
|
||||
agent_id, is_active=True, featured_categories=category
|
||||
)
|
||||
return fastapi.responses.Response(status_code=200)
|
||||
except market.db.AgentQueryError as e:
|
||||
@@ -77,9 +77,8 @@ async def unset_agent_featured(
|
||||
A basic endpoint to unset an agent as featured in the database.
|
||||
"""
|
||||
try:
|
||||
await market.db.set_agent_featured(
|
||||
agent_id, is_featured=False, category=category
|
||||
)
|
||||
|
||||
await market.db.remove_featured_category(agent_id, category=category)
|
||||
return fastapi.responses.Response(status_code=200)
|
||||
except market.db.AgentQueryError as e:
|
||||
raise fastapi.HTTPException(status_code=500, detail=str(e))
|
||||
@@ -159,7 +158,7 @@ async def review_submission(
|
||||
user: autogpt_libs.auth.User = fastapi.Depends(
|
||||
autogpt_libs.auth.requires_admin_user
|
||||
),
|
||||
):
|
||||
) -> prisma.models.Agents | None:
|
||||
"""
|
||||
A basic endpoint to review a submission in the database.
|
||||
"""
|
||||
@@ -167,13 +166,13 @@ async def review_submission(
|
||||
f"Reviewing submission: {review_request.agent_id}, {review_request.version}"
|
||||
)
|
||||
try:
|
||||
# await market.db.update_agent_entry(
|
||||
# agent_id=review_request.agent_id,
|
||||
# version=review_request.version,
|
||||
# submission_state=review_request.status,
|
||||
# comments=review_request.comments,
|
||||
# )
|
||||
return fastapi.responses.Response(status_code=200)
|
||||
agent = await market.db.update_agent_entry(
|
||||
agent_id=review_request.agent_id,
|
||||
version=review_request.version,
|
||||
submission_state=review_request.status,
|
||||
comments=review_request.comments,
|
||||
)
|
||||
return agent
|
||||
except market.db.AgentQueryError as e:
|
||||
raise fastapi.HTTPException(status_code=500, detail=str(e))
|
||||
except Exception as e:
|
||||
|
||||
@@ -248,7 +248,7 @@ async def top_agents_by_downloads(
|
||||
updatedAt=item.agent.updatedAt,
|
||||
views=item.views,
|
||||
downloads=item.downloads,
|
||||
submission_status=item.agent.submissionStatus,
|
||||
submissionStatus=item.agent.submissionStatus,
|
||||
)
|
||||
for item in result.analytics
|
||||
if item.agent is not None
|
||||
@@ -324,7 +324,7 @@ async def get_featured_agents(
|
||||
and len(item.agent.AnalyticsTracker) > 0
|
||||
else 0
|
||||
),
|
||||
submission_status=item.agent.submissionStatus,
|
||||
submissionStatus=item.agent.submissionStatus,
|
||||
)
|
||||
for item in result.featured_agents
|
||||
if item.agent is not None
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import typing
|
||||
|
||||
import fastapi
|
||||
import prisma.enums
|
||||
|
||||
import market.db
|
||||
import market.utils.extension_types
|
||||
@@ -25,6 +26,9 @@ async def search(
|
||||
sort_order: typing.Literal["desc", "asc"] = fastapi.Query(
|
||||
"desc", description="The sort order based on sort_by"
|
||||
),
|
||||
submission_status: prisma.enums.SubmissionStatus = fastapi.Query(
|
||||
None, description="The submission status to filter by"
|
||||
),
|
||||
) -> typing.List[market.utils.extension_types.AgentsWithRank]:
|
||||
"""searches endpoint for agents
|
||||
|
||||
@@ -45,4 +49,5 @@ async def search(
|
||||
description_threshold=description_threshold,
|
||||
sort_by=sort_by,
|
||||
sort_order=sort_order,
|
||||
submission_status=submission_status,
|
||||
)
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `category` on the `FeaturedAgent` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `is_featured` on the `FeaturedAgent` table. All the data in the column will be lost.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "FeaturedAgent" DROP COLUMN "category",
|
||||
DROP COLUMN "is_featured",
|
||||
ADD COLUMN "featuredCategories" TEXT[],
|
||||
ADD COLUMN "isActive" BOOLEAN NOT NULL DEFAULT false;
|
||||
@@ -19,9 +19,9 @@ fuzzywuzzy = "^0.18.0"
|
||||
python-levenshtein = "^0.25.1"
|
||||
# autogpt-server = { path = "../autogpt_server", develop = true }
|
||||
prometheus-fastapi-instrumentator = "^7.0.0"
|
||||
|
||||
|
||||
autogpt-libs = {path = "../autogpt_libs"}
|
||||
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
pytest = "^8.2.1"
|
||||
pytest-asyncio = "^0.23.7"
|
||||
|
||||
@@ -56,9 +56,8 @@ model FeaturedAgent {
|
||||
id String @id @unique @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||
agentId String @unique @db.Uuid
|
||||
agent Agents @relation(fields: [agentId], references: [id])
|
||||
is_featured Boolean @default(false)
|
||||
category String @default("featured")
|
||||
|
||||
isActive Boolean @default(false)
|
||||
featuredCategories String[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user