ronantakizawa/codereview-bench huggingface dataset:
Repository: Significant-Gravitas/Auto-GPT
File: autogpt_platform/frontend/src/lib/utils.ts (TypeScript)

Code before:
    categoryColorMap[categories[0].category] || "bg-gray-300 dark:bg-slate-700"
  );
}

export enum BehaveAs {
  CLOUD = "CLOUD",
  LOCAL = "LOCAL",
}

export function getBehaveAs(): BehaveAs {
  return process.env.NEXT_PUBLIC_BEHAVE_AS === "CLOUD"
    ? BehaveAs.CLOUD
    : BehaveAs.LOCAL;
}

export enum AppEnv {
  LOCAL = "local",
  DEV = "dev",
  PROD = "prod",
}

export function getAppEnv(): AppEnv {
  const env = process.env.NEXT_PUBLIC_APP_ENV;
  if (env === "dev") return AppEnv.DEV;
  if (env === "prod") return AppEnv.PROD;
  // Some places use prod and others production
  if (env === "production") return AppEnv.PROD;
  return AppEnv.LOCAL;
}

export function getEnvironmentStr(): string {
  return `app:${getAppEnv().toLowerCase()}-behave:${getBehaveAs().toLowerCase()}`;
}

function rectanglesOverlap(
  rect1: { x: number; y: number; width: number; height?: number },
  rect2: { x: number; y: number; width: number; height?: number },
): boolean {
  const x1 = rect1.x,
    y1 = rect1.y,
    w1 = rect1.width,
    h1 = rect1.height ?? 100;
  const x2 = rect2.x,
    y2 = rect2.y,
    w2 = rect2.width,
    h2 = rect2.height ?? 100;

  // Check if the rectangles do not overlap
  return !(x1 + w1 <= x2 || x1 >= x2 + w2 || y1 + h1 <= y2 || y1 >= y2 + h2);
}


Review comment (suggestion):
- Moved here from `CustomNode`
- Typed parameters
- Simplified logic
- Fixed recursive handling of arrays of objects

Code after:
      obj[key] ??= propertySchema.default;
    } else if (
      propertySchema.type === "object" &&
      "properties" in propertySchema
    ) {
      // Recursively fill defaults for nested objects
      obj[key] = fillObjectDefaultsFromSchema(obj[key] ?? {}, propertySchema);
    } else if (propertySchema.type === "array") {
      obj[key] ??= [];
      // If the array items are objects, fill their defaults as well
      if (
        Array.isArray(obj[key]) &&
        propertySchema.items?.type === "object" &&
        "properties" in propertySchema.items
      ) {
        for (const item of obj[key]) {
          if (typeof item === "object" && item !== null) {
            fillObjectDefaultsFromSchema(item, propertySchema.items);
          }
        }
      }
    }
  }

  return obj;
}

export const categoryColorMap: Record<string, string> = {
  AI: "bg-orange-300 dark:bg-orange-700",
  SOCIAL: "bg-yellow-300 dark:bg-yellow-700",
  TEXT: "bg-green-300 dark:bg-green-700",
  SEARCH: "bg-blue-300 dark:bg-blue-700",
  BASIC: "bg-purple-300 dark:bg-purple-700",
  INPUT: "bg-cyan-300 dark:bg-cyan-700",
  OUTPUT: "bg-red-300 dark:bg-red-700",
  LOGIC: "bg-teal-300 dark:bg-teal-700",
  DEVELOPER_TOOLS: "bg-fuchsia-300 dark:bg-fuchsia-700",
  AGENT: "bg-lime-300 dark:bg-lime-700",
};

export function getPrimaryCategoryColor(categories: Category[]): string {
  if (categories.length === 0) {
    return "bg-gray-300 dark:bg-slate-700";
  }
  return (
    categoryColorMap[categories[0].category] || "bg-gray-300 dark:bg-slate-700"
  );
}

export enum BehaveAs {
  CLOUD = "CLOUD",
Repository: Significant-Gravitas/Auto-GPT
File: autogpt_platform/frontend/src/components/auth/EmailNotAllowedModal.tsx (TypeScript)

Code before:
import { Button } from "../atoms/Button/Button";
import { Text } from "../atoms/Text/Text";
import { Dialog } from "../molecules/Dialog/Dialog";

interface Props {
  isOpen: boolean;
  onClose: () => void;
}

export function EmailNotAllowedModal({ isOpen, onClose }: Props) {
  return (
    <Dialog
      controlled={{ isOpen, set: onClose }}
      styling={{ maxWidth: "35rem" }}
    >
      <Dialog.Content>
        <div className="flex flex-col items-center gap-8 py-4">
          <Text variant="h3">Join the Waitlist</Text>
          <div className="flex flex-col gap-4">
            <Text variant="large-medium" className="text-center">
              AutoGPT Platform is currently in closed beta. Your email address
              isn&apos;t on our current allowlist for early access.
            </Text>
            <Text variant="body" className="text-center">
              Join our waitlist to get notified when we open up access!
            </Text>
          </div>
          <div className="flex gap-3">
            <Button
              variant="secondary"
              onClick={() => {
                window.open("https://agpt.co/waitlist", "_blank");
              }}
            >
              Join Waitlist
            </Button>
            <Button variant="primary" onClick={onClose}>
              Close
            </Button>
          </div>
          <div className="flex flex-col gap-2">
            <Text variant="small" className="text-center text-muted-foreground">
              Already signed up for the waitlist? Make sure you&apos;re using
              the exact same email address you used when signing up.
            </Text>
            <Text variant="small" className="text-center text-muted-foreground">

Review comment (suggestion):
```suggestion
              The AutoGPT Platform is currently in closed beta. Your email address
```

Code after:
import { Dialog } from "../molecules/Dialog/Dialog";
import { WaitlistErrorContent } from "./WaitlistErrorContent";

interface Props {
  isOpen: boolean;
  onClose: () => void;
}

export function EmailNotAllowedModal({ isOpen, onClose }: Props) {
  return (
    <Dialog
      controlled={{ isOpen, set: onClose }}
      styling={{ maxWidth: "35rem" }}
    >
      <Dialog.Content>
        <div className="py-4">
          <WaitlistErrorContent onClose={onClose} />
        </div>
      </Dialog.Content>
    </Dialog>
  );
}
Repository: Significant-Gravitas/Auto-GPT
File: autogpt_platform/backend/backend/data/graph.py (Python)

Code before:

    if version is not None:
        where_clause["version"] = version

    graph = await AgentGraph.prisma().find_first(
        where=where_clause,
        order={"version": "desc"},
    )

    if not graph:
        return None

    return Graph(
        id=graph.id,
        name=graph.name or "",
        description=graph.description or "",
        version=graph.version,
        is_active=graph.isActive,
    )


async def get_graph(
    graph_id: str,
    version: int | None = None,
    *,
    user_id: str | None = None,
    for_export: bool = False,
    include_subgraphs: bool = False,
    skip_access_check: bool = False,
) -> GraphModel | None:
    """
    Retrieves a graph from the DB.
    Defaults to the version with `is_active` if `version` is not passed.

    Returns `None` if the record is not found.
    """
    where_clause: AgentGraphWhereInput = {
        "id": graph_id,
    }

    if version is not None:
        where_clause["version"] = version

    graph = await AgentGraph.prisma().find_first(
        where=where_clause,
        include=AGENT_GRAPH_INCLUDE,
        order={"version": "desc"},
    )
    if graph is None:
        return None


Review comment (security):
`skip_access_check` is security-sensitive and should thus be a kwarg to prevent confusion with e.g. `include_subgraphs`. In this case I made a few more parameters also kwargs because that's much clearer and they are already being specified that way in most places.

Code after:
    }

    if version is not None:
        where_clause["version"] = version

    graph = await AgentGraph.prisma().find_first(
        where=where_clause,
        order={"version": "desc"},
    )

    if not graph:
        return None

    return Graph(
        id=graph.id,
        name=graph.name or "",
        description=graph.description or "",
        version=graph.version,
        is_active=graph.isActive,
    )


async def get_graph(
    graph_id: str,
    version: int | None = None,
    *,
    user_id: str | None = None,
    for_export: bool = False,
    include_subgraphs: bool = False,
    skip_access_check: bool = False,
) -> GraphModel | None:
    """
    Retrieves a graph from the DB.
    Defaults to the version with `is_active` if `version` is not passed.

    Returns `None` if the record is not found.
    """
    where_clause: AgentGraphWhereInput = {
        "id": graph_id,
    }

    if version is not None:
        where_clause["version"] = version

    graph = await AgentGraph.prisma().find_first(
        where=where_clause,
        include=AGENT_GRAPH_INCLUDE,
        order={"version": "desc"},
    )
    if graph is None:
        return None
Repository: Significant-Gravitas/Auto-GPT
File: autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/Flow/Flow.tsx (TypeScript)

Code before:
      availableBlocks,
      nodes,
      edges,
      addNodes,
      screenToFlowPosition,
      deleteElements,
      clearNodesStatusAndOutput,
    ],
  );

  return (
    <BuilderContext.Provider
      value={{
        nodes,
        libraryAgent,
        visualizeBeads,
        setIsAnyModalOpen,
        getNextNodeId,
      }}
    >
      <div className={className}>
        <ReactFlow
          nodes={nodes.map((node) => ({
            ...node,
            position: immediateNodePositions[node.id] || node.position,
          }))}
          edges={edges}
          nodeTypes={{ custom: CustomNode }}
          edgeTypes={{ custom: CustomEdge }}
          connectionLineComponent={ConnectionLine}
          onConnect={onConnect}
          onNodesChange={onNodesChange}
          onNodesDelete={onNodesDelete}
          onEdgesChange={onEdgesChange}
          onNodeDragStop={onNodeDragEnd}
          onNodeDragStart={onNodeDragStart}
          onDrop={onDrop}
          onDragOver={onDragOver}
          deleteKeyCode={["Backspace", "Delete"]}
          minZoom={0.1}
          maxZoom={2}
          className="dark:bg-slate-900"
        >
          <Controls />
          <Background className="dark:bg-slate-800" />
          {isNewBlockEnabled ? (
            <NewControlPanel
              flowExecutionID={flowExecutionID}
              visualizeBeads={visualizeBeads}
              pinSavePopover={pinSavePopover}
              pinBlocksPopover={pinBlocksPopover}

Review comment (suggestion):
Somehow these frontend changes cause the entire `FlowEditor` to re-render continuously while dragging nodes.

Code after:
        history.push({
          type: "ADD_NODE",
          payload: { node: { ...newNode, ...newNode.data } },
          undo: () => {
            deleteElements({ nodes: [{ id: newNode.id } as any], edges: [] });
          },
          redo: () => {
            addNodes([newNode]);
          },
        });
        addNodes([newNode]);
        clearNodesStatusAndOutput();

        setNodeId((prevId) => prevId + 1);
      } catch (error) {
        console.error("Failed to drop block:", error);
      }
    },
    [
      nodeId,
      availableBlocks,
      nodes,
      edges,
      addNodes,
      screenToFlowPosition,
      deleteElements,
      clearNodesStatusAndOutput,
    ],
  );

  const buildContextValue: BuilderContextType = useMemo(
    () => ({
      libraryAgent,
      visualizeBeads,
      setIsAnyModalOpen,
      getNextNodeId,
      getNodeTitle,
    }),
    [libraryAgent, visualizeBeads, getNextNodeId, getNodeTitle],
  );

  return (
    <BuilderContext.Provider value={buildContextValue}>
      <div className={className}>
        <ReactFlow
          nodes={nodes.map((node) =>
            node.id in immediateNodePositions
              ? {
                  ...node,
                  position: immediateNodePositions[node.id] || node.position,
                }
Repository: Significant-Gravitas/Auto-GPT
File: autogpt_platform/backend/backend/util/exceptions.py (Python)

Code before:
from typing import Mapping


class BlockError(Exception):
    """An error occurred during the running of a block"""

    def __init__(self, message: str, block_name: str, block_id: str) -> None:
        super().__init__(message)
        self.message = message
        self.block_name = block_name
        self.block_id = block_id

    def __str__(self):
        return f"raised by {self.block_name} with message: {self.message}. block_id: {self.block_id}"


class BlockValueError(BlockError): ...


class BlockRuntimeError(BlockError): ...


class BlockUnknownError(BlockError): ...


class MissingConfigError(Exception):
    """The attempted operation requires configuration which is not available"""


class NotFoundError(ValueError):
    """The requested record was not found, resulting in an error condition"""


class NeedConfirmation(Exception):
    """The user must explicitly confirm that they want to proceed"""


class NotAuthorizedError(ValueError):
    """The user is not authorized to perform the requested operation"""


class GraphNotAccessibleError(NotAuthorizedError):
    """Raised when attempting to execute a graph that is not accessible to the user."""



Review comment (suggestion):
This also needs to extend ValueError, see: https://github.com/Significant-Gravitas/AutoGPT/blob/dev/autogpt_platform/backend/backend/executor/manager.py#L579-L596

This can be BlockExecutionError since RuntimeError is another real python error and can be misleading 

Code after:
from typing import Mapping


class BlockError(Exception):
    """An error occurred during the running of a block"""

    def __init__(self, message: str, block_name: str, block_id: str) -> None:
        super().__init__(message)
        self.message = message
        self.block_name = block_name
        self.block_id = block_id

    def __str__(self):
        return f"raised by {self.block_name} with message: {self.message}. block_id: {self.block_id}"


class BlockInputError(BlockError, ValueError):
    """The block had incorrect inputs, resulting in an error condition"""


class BlockOutputError(BlockError, ValueError):
    """The block had incorrect outputs, resulting in an error condition"""


class BlockExecutionError(BlockError, ValueError):
    """The block failed to execute at runtime, resulting in a handled error"""


class BlockUnknownError(BlockError):
    """Critical unknown error with block handling"""


class MissingConfigError(Exception):
    """The attempted operation requires configuration which is not available"""


class NotFoundError(ValueError):
    """The requested record was not found, resulting in an error condition"""


class NeedConfirmation(Exception):
    """The user must explicitly confirm that they want to proceed"""


class NotAuthorizedError(ValueError):
Repository: Significant-Gravitas/Auto-GPT
File: autogpt_platform/backend/backend/blocks/codex.py (Python)

Code before:
        return {
            "response": text_output,
            "reasoning": reasoning_summary,
            "response_id": response_id,
        }

    async def run(
        self,
        input_data: Input,
        *,
        credentials: APIKeyCredentials,
        **kwargs,
    ) -> BlockOutput:
        try:
            result = await self.call_codex(
                credentials=credentials,
                model=input_data.model,
                prompt=input_data.prompt,
                system_prompt=input_data.system_prompt,
                max_output_tokens=input_data.max_output_tokens,
                reasoning_effort=input_data.reasoning_effort,
            )
        except Exception as exc:  # pragma: no cover - defensive logging
            error_msg = f"Codex request failed: {exc}"
            logger.error(error_msg)
            yield "error", error_msg
            return

        yield "response", result["response"]
        yield "reasoning", result.get("reasoning", "")
        yield "response_id", result.get("response_id", "")

    @staticmethod
    def _extract_output_text(response: Any) -> str:
        """Best-effort extraction of the aggregated text output."""
        if not response:
            return ""

        output_text = getattr(response, "output_text", None)
        if output_text:
            if isinstance(output_text, list):
                return "".join(str(part) for part in output_text)
            return str(output_text)

        aggregated_parts: list[str] = []
        output_items = getattr(response, "output", None) or []
        for item in output_items:
            content_list = getattr(item, "content", None) or []
            for content in content_list:
                text_value = getattr(content, "text", None)
                if text_value:

Review comment (suggestion):
We've been logging errors, just re-raise it with ValueError if it's a known error, or no need to raise it at all if it's unknown (and we want it to go to sentry).

Code after:

        return CodexCallResult(
            response=text_output,
            reasoning=reasoning_summary,
            response_id=response_id,
        )

    async def run(
        self,
        input_data: Input,
        *,
        credentials: APIKeyCredentials,
        **_kwargs,
    ) -> BlockOutput:
        result = await self.call_codex(
            credentials=credentials,
            model=input_data.model,
            prompt=input_data.prompt,
            system_prompt=input_data.system_prompt,
            max_output_tokens=input_data.max_output_tokens,
            reasoning_effort=input_data.reasoning_effort,
        )

        yield "response", result.response
        yield "reasoning", result.reasoning
        yield "response_id", result.response_id
Repository: Significant-Gravitas/Auto-GPT
File: autogpt_platform/frontend/src/app/(platform)/build/components/FlowEditor/edges/CustomEdge.tsx (TypeScript)

Code before:
  return (
    <>
      <BaseEdge
        path={edgePath}
        markerEnd={markerEnd}
        className={cn(
          isStatic && "!stroke-[1.5px] [stroke-dasharray:6]",
          selected
            ? "stroke-zinc-800"
            : "stroke-zinc-500/50 hover:stroke-zinc-500",
        )}
      />
      <JSBeads
        beadUp={beadUp}
        beadDown={beadDown}
        edgePath={edgePath}
        beadsKey={`beads-${id}-${sourceX}-${sourceY}-${targetX}-${targetY}`}
      />
      <EdgeLabelRenderer>
        <Button
          onClick={() => removeConnection(id)}
          className={`absolute h-fit min-w-0 p-1`}
          variant="secondary"
          style={{
            transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`,
            pointerEvents: "all",
          }}
        >
          <XIcon className="h-3 w-3" weight="bold" />
        </Button>
      </EdgeLabelRenderer>
    </>
  );
};

export default memo(CustomEdge);


Review comment (bug):
I would use `hidden` / `block`. With opacity, the button is still there. A quick misclick on that area will trigger the delete action, making the user think it is a bug 🐛 

Code after:
  const beadDown = data?.beadDown ?? 0;

  return (
    <>
      <BaseEdge
        path={edgePath}
        markerEnd={markerEnd}
        className={cn(
          isStatic && "!stroke-[1.5px] [stroke-dasharray:6]",
          selected
            ? "stroke-zinc-800"
            : "stroke-zinc-500/50 hover:stroke-zinc-500",
        )}
      />
      <JSBeads
        beadUp={beadUp}
        beadDown={beadDown}
        edgePath={edgePath}
        beadsKey={`beads-${id}-${sourceX}-${sourceY}-${targetX}-${targetY}`}
      />
      <EdgeLabelRenderer>
        <Button
          onClick={() => removeConnection(id)}
          className={cn(
            "absolute h-fit min-w-0 p-1 transition-opacity",
            isHovered ? "opacity-100" : "opacity-0",
          )}
          variant="secondary"
          style={{
            transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`,
            pointerEvents: "all",
          }}
          onMouseEnter={() => setIsHovered(true)}
          onMouseLeave={() => setIsHovered(false)}
        >
          <XIcon className="h-3 w-3" weight="bold" />
        </Button>
      </EdgeLabelRenderer>
    </>
  );
};

export default memo(CustomEdge);
Repository: Significant-Gravitas/Auto-GPT
File: autogpt_platform/backend/backend/data/workspace.py (Python)

Code before:
            "metadata": SafeJson(metadata or {}),
        }
    )

    logger.info(
        f"Created workspace file {file.id} at path {path} "
        f"in workspace {workspace_id}"
    )
    return WorkspaceFile.from_db(file)


async def get_workspace_file(
    file_id: str,
    workspace_id: str,
) -> Optional[WorkspaceFile]:
    """
    Get a workspace file by ID.

    Args:
        file_id: The file ID
        workspace_id: Workspace ID for scoping (required)

    Returns:
        WorkspaceFile instance or None
    """
    where_clause: dict = {
        "id": file_id,
        "isDeleted": False,
        "workspaceId": workspace_id,
    }

    file = await UserWorkspaceFile.prisma().find_first(where=where_clause)
    return WorkspaceFile.from_db(file) if file else None


async def get_workspace_file_by_path(
    workspace_id: str,
    path: str,
) -> Optional[WorkspaceFile]:
    """
    Get a workspace file by its virtual path.

    Args:
        workspace_id: The workspace ID
        path: Virtual path

    Returns:
        WorkspaceFile instance or None
    """
    # Normalize path
    if not path.startswith("/"):

Review comment (suggestion):
```suggestion
    where_clause: UserWorkspaceFileWhereInput = {
```

Code after:
            "metadata": SafeJson(metadata or {}),
        }
    )

    logger.info(
        f"Created workspace file {file.id} at path {path} "
        f"in workspace {workspace_id}"
    )
    return WorkspaceFile.from_db(file)


async def get_workspace_file(
    file_id: str,
    workspace_id: str,
) -> Optional[WorkspaceFile]:
    """
    Get a workspace file by ID.

    Args:
        file_id: The file ID
        workspace_id: Workspace ID for scoping (required)

    Returns:
        WorkspaceFile instance or None
    """
    where_clause: UserWorkspaceFileWhereInput = {
        "id": file_id,
        "isDeleted": False,
        "workspaceId": workspace_id,
    }

    file = await UserWorkspaceFile.prisma().find_first(where=where_clause)
    return WorkspaceFile.from_db(file) if file else None


async def get_workspace_file_by_path(
    workspace_id: str,
    path: str,
) -> Optional[WorkspaceFile]:
    """
    Get a workspace file by its virtual path.

    Args:
        workspace_id: The workspace ID
        path: Virtual path

    Returns:
        WorkspaceFile instance or None
    """
    # Normalize path
    if not path.startswith("/"):