diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9683ddf848a1..87d66db13dde 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,5 +1,7 @@ -.github/workflows/ @Significant-Gravitas/devops -autogpt/ @Significant-Gravitas/maintainers -forge/ @Significant-Gravitas/forge-maintainers -benchmark/ @Significant-Gravitas/benchmark-maintainers -frontend/ @Significant-Gravitas/frontend-maintainers +* @Significant-Gravitas/maintainers +.github/workflows/ @Significant-Gravitas/devops +forge/ @Significant-Gravitas/forge-maintainers +benchmark/ @Significant-Gravitas/benchmark-maintainers +frontend/ @Significant-Gravitas/frontend-maintainers +rnd/infra @Significant-Gravitas/devops +.github/CODEOWNERS @Significant-Gravitas/admins diff --git a/rnd/autogpt_builder/package.json b/rnd/autogpt_builder/package.json index 908d1cd4b087..be61827b421e 100644 --- a/rnd/autogpt_builder/package.json +++ b/rnd/autogpt_builder/package.json @@ -16,7 +16,6 @@ "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-popover": "^1.1.1", - "@radix-ui/react-select": "^2.1.1", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-switch": "^1.1.0", "@radix-ui/react-tooltip": "^1.1.2", diff --git a/rnd/autogpt_builder/src/components/CustomNode.tsx b/rnd/autogpt_builder/src/components/CustomNode.tsx index 911f54457daa..8ed9844ea8e4 100644 --- a/rnd/autogpt_builder/src/components/CustomNode.tsx +++ b/rnd/autogpt_builder/src/components/CustomNode.tsx @@ -5,12 +5,13 @@ import './customnode.css'; import InputModalComponent from './InputModalComponent'; import OutputModalComponent from './OutputModalComponent'; import { BlockIORootSchema, NodeExecutionResult } from '@/lib/autogpt-server-api/types'; +import { BlockSchema } from '@/lib/types'; import { beautifyString, setNestedProperty } from '@/lib/utils'; import { Switch } from "@/components/ui/switch" import NodeHandle from './NodeHandle'; +import NodeInputField from './NodeInputField'; import { Copy, Trash2 } from 'lucide-react'; import { history } from './history'; -import { NodeGenericInputField } from './node-input'; export type CustomNodeData = { blockType: string; @@ -21,8 +22,8 @@ export type CustomNodeData = { setHardcodedValues: (values: { [key: string]: any }) => void; connections: Array<{ source: string; sourceHandle: string; target: string; targetHandle: string }>; isOutputOpen: boolean; - status?: NodeExecutionResult["status"]; - output_data?: NodeExecutionResult["output_data"]; + status?: string; + output_data?: any; block_id: string; backend_id?: string; errors?: { [key: string]: string | null }; @@ -118,7 +119,7 @@ const CustomNode: FC> = ({ data, id }) => { const getValue = (key: string) => { const keys = key.split('.'); - return keys.reduce((acc, k) => acc && acc[k] ? acc[k] : undefined, data.hardcodedValues); + return keys.reduce((acc, k) => (acc && acc[k] !== undefined) ? acc[k] : '', data.hardcodedValues); }; const isHandleConnected = (key: string) => { @@ -247,36 +248,28 @@ const CustomNode: FC> = ({ data, id }) => { )} -
+
{data.inputSchema && - Object.entries(data.inputSchema.properties).map(([propKey, propSchema]) => { - const isRequired = data.inputSchema.required?.includes(propKey); + Object.entries(data.inputSchema.properties).map(([key, schema]) => { + const isRequired = data.inputSchema.required?.includes(key); return (isRequired || isAdvancedOpen) && ( -
{ }}> - - {!isHandleConnected(propKey) && - { }}> + + {!isHandleConnected(key) && + - } + handleInputChange={handleInputChange} + errors={data.errors?.[key]} + />}
); })}
-
+
{data.outputSchema && generateOutputHandles(data.outputSchema)}
@@ -303,11 +296,11 @@ const CustomNode: FC> = ({ data, id }) => {
)}
- + Output {hasOptionalFields() && ( <> - + Advanced )} diff --git a/rnd/autogpt_builder/src/components/Flow.tsx b/rnd/autogpt_builder/src/components/Flow.tsx index 02a71cfd7680..93a435c0124f 100644 --- a/rnd/autogpt_builder/src/components/Flow.tsx +++ b/rnd/autogpt_builder/src/components/Flow.tsx @@ -15,7 +15,7 @@ import ReactFlow, { import 'reactflow/dist/style.css'; import CustomNode, { CustomNodeData } from './CustomNode'; import './flow.css'; -import AutoGPTServerAPI, { Block, BlockIOSubSchema, Graph, NodeExecutionResult } from '@/lib/autogpt-server-api'; +import AutoGPTServerAPI, { Block, BlockIOSchema, Graph, NodeExecutionResult, ObjectSchema } from '@/lib/autogpt-server-api'; import { Button } from './ui/button'; import { Input } from './ui/input'; import { ChevronRight, ChevronLeft } from "lucide-react"; @@ -392,6 +392,7 @@ const FlowEditor: React.FC<{ type: 'custom', position: { x: node.metadata.position.x, y: node.metadata.position.y }, data: { + setIsAnyModalOpen: setIsAnyModalOpen, block_id: block.id, blockType: block.name, title: `${block.name} ${node.id}`, @@ -452,7 +453,7 @@ const FlowEditor: React.FC<{ } const getNestedData = ( - schema: BlockIOSubSchema, values: { [key: string]: any } + schema: BlockIOSchema, values: { [key: string]: any } ): { [key: string]: any } => { let inputData: { [key: string]: any } = {}; @@ -601,7 +602,7 @@ const FlowEditor: React.FC<{ // Populate errors if validation fails validate.errors?.forEach((error) => { // Skip error if there's an edge connected - const path = 'dataPath' in error ? error.dataPath as string : error.instancePath; + const path = error.instancePath || error.schemaPath; const handle = path.split(/[\/.]/)[0]; if (node.data.connections.some(conn => conn.target === node.id || conn.targetHandle === handle)) { return; diff --git a/rnd/autogpt_builder/src/components/NodeHandle.tsx b/rnd/autogpt_builder/src/components/NodeHandle.tsx index 73a7011c5c32..9eb0c4a70446 100644 --- a/rnd/autogpt_builder/src/components/NodeHandle.tsx +++ b/rnd/autogpt_builder/src/components/NodeHandle.tsx @@ -1,4 +1,4 @@ -import { BlockIOSubSchema } from "@/lib/autogpt-server-api/types"; +import { BlockIOSchema } from "@/lib/autogpt-server-api/types"; import { beautifyString, getTypeBgColor, getTypeTextColor } from "@/lib/utils"; import { FC } from "react"; import { Handle, Position } from "reactflow"; @@ -6,7 +6,7 @@ import SchemaTooltip from "./SchemaTooltip"; type HandleProps = { keyName: string, - schema: BlockIOSubSchema, + schema: BlockIOSchema, isConnected: boolean, isRequired?: boolean, side: 'left' | 'right' @@ -23,19 +23,19 @@ const NodeHandle: FC = ({ keyName, schema, isConnected, isRequired, null: 'null', }; - const typeClass = `text-sm ${getTypeTextColor(schema.type || 'any')} ${side === 'left' ? 'text-left' : 'text-right'}`; + const typeClass = `text-sm ${getTypeTextColor(schema.type)} ${side === 'left' ? 'text-left' : 'text-right'}`; const label = (
{schema.title || beautifyString(keyName)}{isRequired ? '*' : ''} - {typeName[schema.type] || 'any'} + {typeName[schema.type]}
); const dot = ( -
+
); if (side === 'left') { @@ -45,7 +45,7 @@ const NodeHandle: FC = ({ keyName, schema, isConnected, isRequired, type="target" position={Position.Left} id={keyName} - className='group -ml-[26px]' + className='group -ml-[29px]' >
{dot} @@ -62,7 +62,7 @@ const NodeHandle: FC = ({ keyName, schema, isConnected, isRequired, type="source" position={Position.Right} id={keyName} - className='group -mr-[26px]' + className='group -mr-[29px]' >
{label} diff --git a/rnd/autogpt_builder/src/components/NodeInputField.tsx b/rnd/autogpt_builder/src/components/NodeInputField.tsx new file mode 100644 index 000000000000..42adae4667d9 --- /dev/null +++ b/rnd/autogpt_builder/src/components/NodeInputField.tsx @@ -0,0 +1,294 @@ +import { Cross2Icon, PlusIcon } from "@radix-ui/react-icons"; +import { beautifyString } from "@/lib/utils"; +import { BlockIOSchema } from "@/lib/autogpt-server-api/types"; +import { FC, useState } from "react"; +import { Button } from "./ui/button"; +import { Input } from "./ui/input"; + +type BlockInputFieldProps = { + keyName: string + schema: BlockIOSchema + parentKey?: string + value: string | Array | { [key: string]: string } + handleInputClick: (key: string) => void + handleInputChange: (key: string, value: any) => void + errors?: { [key: string]: string } | string | null +} + +const NodeInputField: FC = ({ + keyName: key, + schema, + parentKey = '', + value, + handleInputClick, + handleInputChange, + errors +}) => { + const fullKey = parentKey ? `${parentKey}.${key}` : key; + const error = typeof errors === 'string' ? errors : errors?.[key] ?? ""; + const displayKey = schema.title || beautifyString(key); + + const [keyValuePairs, _setKeyValuePairs] = useState<{ key: string, value: string }[]>( + "additionalProperties" in schema && value + ? Object.entries(value).map(([key, value]) => ({ key: key, value: value })) + : [] + ); + + function setKeyValuePairs(newKVPairs: typeof keyValuePairs): void { + _setKeyValuePairs(newKVPairs); + handleInputChange( + fullKey, + newKVPairs.reduce((obj, { key, value }) => ({ ...obj, [key]: value }), {}) + ); + } + + const renderClickableInput = (value: string | null = null, placeholder: string = "", secret: boolean = false) => { + const className = `clickable-input ${error ? 'border-error' : ''}`; + + return secret ? ( +
handleInputClick(fullKey)}> + {value ? ******** : {placeholder}} +
+ ) : ( +
handleInputClick(fullKey)}> + {value || {placeholder}} +
+ ); + }; + + if ("properties" in schema) { + return ( +
+ {displayKey}: + {Object.entries(schema.properties).map(([propKey, propSchema]) => ( +
+ +
+ ))} +
+ ); + } + + if (schema.type === 'object' && schema.additionalProperties) { + return ( +
+
+ {keyValuePairs.map(({ key, value }, index) => ( +
+ setKeyValuePairs( + keyValuePairs.toSpliced(index, 1, { + key: e.target.value, value: value + }) + )} + /> + setKeyValuePairs( + keyValuePairs.toSpliced(index, 1, { + key: key, value: e.target.value + }) + )} + /> + +
+ ))} + +
+ {error && {error}} +
+ ); + } + + if ("anyOf" in schema) { + const types = schema.anyOf.map(s => "type" in s ? s.type : undefined); + if (types.includes('string') && types.includes('null')) { + return ( +
+ {renderClickableInput(value as string, schema.placeholder || `Enter ${displayKey} (optional)`)} + {error && {error}} +
+ ); + } + } + + if ("allOf" in schema) { + return ( +
+ {displayKey}: + {"properties" in schema.allOf[0] && + Object.entries(schema.allOf[0].properties).map(([propKey, propSchema]) => ( +
+ +
+ ))} +
+ ); + } + + if ("oneOf" in schema) { + return ( +
+ {displayKey}: + {"properties" in schema.oneOf[0] && + Object.entries(schema.oneOf[0].properties).map(([propKey, propSchema]) => ( +
+ +
+ ))} +
+ ); + } + + if (!("type" in schema)) { + console.warn(`Schema for input ${key} does not specify a type:`, schema); + return ( +
+ {renderClickableInput(value as string, schema.placeholder || `Enter ${beautifyString(displayKey)} (Complex)`)} + {error && {error}} +
+ ); + } + + switch (schema.type) { + case 'string': + if (schema.enum) { + return ( +
+ + {error && {error}} +
+ ); + } + + if (schema.secret) { + return ( +
+ {renderClickableInput(value as string, schema.placeholder || `Enter ${displayKey}`, true)} + {error && {error}} +
+ ); + } + + return ( +
+ {renderClickableInput(value as string, schema.placeholder || `Enter ${displayKey}`)} + {error && {error}} +
+ ); + case 'boolean': + return ( +
+ + {error && {error}} +
+ ); + case 'number': + case 'integer': + return ( +
+ handleInputChange(fullKey, parseFloat(e.target.value))} + className={`number-input ${error ? 'border-error' : ''}`} + /> + {error && {error}} +
+ ); + case 'array': + if (schema.items && schema.items.type === 'string') { + const arrayValues = value as Array || []; + return ( +
+ {arrayValues.map((item: string, index: number) => ( +
+ handleInputChange(`${fullKey}.${index}`, e.target.value)} + className="array-item-input" + /> + +
+ ))} + + {error && {error}} +
+ ); + } + return null; + default: + console.warn(`Schema for input ${key} specifies unknown type:`, schema); + return ( +
+ {renderClickableInput(value as string, schema.placeholder || `Enter ${beautifyString(displayKey)} (Complex)`)} + {error && {error}} +
+ ); + } +}; + +export default NodeInputField; diff --git a/rnd/autogpt_builder/src/components/SchemaTooltip.tsx b/rnd/autogpt_builder/src/components/SchemaTooltip.tsx index ca8c686a95ca..52357eaa6f15 100644 --- a/rnd/autogpt_builder/src/components/SchemaTooltip.tsx +++ b/rnd/autogpt_builder/src/components/SchemaTooltip.tsx @@ -4,11 +4,11 @@ import { TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip" -import { BlockIOSubSchema } from "@/lib/autogpt-server-api/types"; +import { BlockIOSchema } from "@/lib/autogpt-server-api/types"; import { Info } from 'lucide-react'; import ReactMarkdown from 'react-markdown'; -const SchemaTooltip: React.FC<{ schema: BlockIOSubSchema }> = ({ schema }) => { +const SchemaTooltip: React.FC<{ schema: BlockIOSchema }> = ({ schema }) => { if (!schema.description) return null; return ( diff --git a/rnd/autogpt_builder/src/components/customnode.css b/rnd/autogpt_builder/src/components/customnode.css index 1288112024ba..c6968fed739a 100644 --- a/rnd/autogpt_builder/src/components/customnode.css +++ b/rnd/autogpt_builder/src/components/customnode.css @@ -1,5 +1,5 @@ .custom-node { - @apply p-3; + padding: 15px; border: 3px solid #4b5563; border-radius: 12px; background: #ffffff; @@ -89,6 +89,10 @@ transform: none; } +.input-container { + margin-bottom: 5px; +} + .clickable-input { padding: 5px; width: 325px; @@ -187,9 +191,29 @@ .error-message { color: #d9534f; - font-size: 13px; + font-size: 12px; margin-top: 5px; - margin-left: 5px; +} + +.object-input { + margin-left: 10px; + border-left: 1px solid #000; /* Border for nested inputs */ + padding-left: 10px; +} + +.nested-input { + margin-top: 5px; +} + +.key-value-input { + display: flex; + gap: 5px; + align-items: center; + margin-bottom: 5px; +} + +.key-value-input input { + flex-grow: 1; } /* Styles for node states */ diff --git a/rnd/autogpt_builder/src/components/flow.css b/rnd/autogpt_builder/src/components/flow.css index 546e76e7a2f8..c275f3104a7d 100644 --- a/rnd/autogpt_builder/src/components/flow.css +++ b/rnd/autogpt_builder/src/components/flow.css @@ -126,3 +126,24 @@ input::placeholder, textarea::placeholder { width: 100%; height: 600px; /* Adjust this height as needed */ } + +.flow-wrapper { + height: 100%; + width: 100%; + display: flex; + justify-content: center; + align-items: center; +} + +.flow-controls { + position: absolute; + left: -80px; + z-index: 1001; + display: flex; + gap: 10px; + transition: transform 0.3s ease; +} + +.flow-controls.open { + transform: translateX(350px); +} diff --git a/rnd/autogpt_builder/src/components/node-input.tsx b/rnd/autogpt_builder/src/components/node-input.tsx deleted file mode 100644 index 550aa71ff2ee..000000000000 --- a/rnd/autogpt_builder/src/components/node-input.tsx +++ /dev/null @@ -1,545 +0,0 @@ -import { Cross2Icon, Pencil2Icon, PlusIcon } from "@radix-ui/react-icons"; -import { beautifyString, cn } from "@/lib/utils"; -import { - BlockIORootSchema, - BlockIOSubSchema, - BlockIOObjectSubSchema, - BlockIOKVSubSchema, - BlockIOArraySubSchema, - BlockIOStringSubSchema, - BlockIONumberSubSchema, - BlockIOBooleanSubSchema, -} from "@/lib/autogpt-server-api/types"; -import { FC, useState } from "react"; -import { Button } from "./ui/button"; -import { Switch } from "./ui/switch"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./ui/select"; -import { Input } from "./ui/input"; -import { Label } from "./ui/label"; - -type NodeObjectInputTreeProps = { - selfKey?: string; - schema: BlockIORootSchema | BlockIOObjectSubSchema; - object?: { [key: string]: any }; - handleInputClick: (key: string) => void; - handleInputChange: (key: string, value: any) => void; - errors: { [key: string]: string | undefined }; - className?: string; - displayName?: string; -}; - -const NodeObjectInputTree: FC = ({ - selfKey = "", - schema, - object, - handleInputClick, - handleInputChange, - errors, - className, - displayName, -}) => { - object ??= ("default" in schema ? schema.default : null) ?? {}; - return ( -
- {displayName && {displayName}:} - {Object.entries(schema.properties).map(([propKey, propSchema]) => { - const childKey = selfKey ? `${selfKey}.${propKey}` : propKey; - - return ( -
- {propKey} - -
- ) - })} -
- ); -}; - -export default NodeObjectInputTree; - -export const NodeGenericInputField: FC<{ - propKey: string; - propSchema: BlockIOSubSchema; - currentValue?: any; - errors: NodeObjectInputTreeProps["errors"]; - handleInputChange: NodeObjectInputTreeProps["handleInputChange"]; - handleInputClick: NodeObjectInputTreeProps["handleInputClick"]; - className?: string; - displayName?: string; -}> = ({ - propKey, - propSchema, - currentValue, - errors, - handleInputChange, - handleInputClick, - className, - displayName, -}) => { - displayName ??= propSchema.title || beautifyString(propKey); - - if ("allOf" in propSchema) { - // If this happens, that is because Pydantic wraps $refs in an allOf if the - // $ref has sibling schema properties (which isn't technically allowed), - // so there will only be one item in allOf[]. - // AFAIK this should NEVER happen though, as $refs are resolved server-side. - propSchema = propSchema.allOf[0]; - console.warn(`Unsupported 'allOf' in schema for '${propKey}'!`, propSchema); - } - - if ("properties" in propSchema) { - return ( - - ); - } - - if ("additionalProperties" in propSchema) { - return ( - - ); - } - - if ("anyOf" in propSchema) { // optional items - const types = propSchema.anyOf.map((s) => ("type" in s ? s.type : undefined)); - if (types.includes("string") && types.includes("null")) { // optional string - return ( - - ); - } - } - - if ("oneOf" in propSchema) { - // At the time of writing, this isn't used in the backend -> no impl. needed - console.error(`Unsupported 'oneOf' in schema for '${propKey}'!`, propSchema); - return null; - } - - if (!("type" in propSchema)) { - return ( - - ); - } - - switch (propSchema.type) { - case "string": - return ( - - ); - case "boolean": - return ( - - ); - case "number": - case "integer": - return ( - - ); - case "array": - return ( - - ); - default: - console.warn(`Schema for '${propKey}' specifies unknown type:`, propSchema); - return ( - - ); - } - } - -const NodeKeyValueInput: FC<{ - selfKey: string; - schema: BlockIOKVSubSchema; - entries?: { [key: string]: string } | { [key: string]: number }; - errors: { [key: string]: string | undefined }; - handleInputChange: NodeObjectInputTreeProps["handleInputChange"]; - className?: string; - displayName?: string; -}> = ({ selfKey, entries, schema, handleInputChange, errors, className, displayName }) => { - const [keyValuePairs, setKeyValuePairs] = useState<{ - key: string; - value: string | number | null; - }[]>( - Object.entries(entries ?? schema.default ?? {}) - .map(([key, value]) => ({ key, value: value })) - ); - - function updateKeyValuePairs(newPairs: typeof keyValuePairs) { - setKeyValuePairs(newPairs); - handleInputChange( - selfKey, - newPairs.reduce((obj, { key, value }) => ({ ...obj, [key]: value }), {}) - ); - }; - - function convertValueType(value: string): string | number | null { - if (schema.additionalProperties.type == "string") return value; - if (!value) return null; - return Number(value) - } - - return ( -
- {displayName && {displayName}:} -
- {keyValuePairs.map(({ key, value }, index) => ( -
-
- - updateKeyValuePairs( - keyValuePairs.toSpliced(index, 1, { - key: e.target.value, - value: value, - }) - ) - } - /> - - updateKeyValuePairs( - keyValuePairs.toSpliced(index, 1, { - key: key, - value: convertValueType(e.target.value), - }) - ) - } - /> - -
- {errors[`${selfKey}.${key}`] && - {errors[`${selfKey}.${key}`]} - } -
- ))} - -
- {errors[selfKey] && {errors[selfKey]}} -
- ); -}; - -const NodeArrayInput: FC<{ - selfKey: string; - schema: BlockIOArraySubSchema; - entries?: string[]; - errors: { [key: string]: string | undefined }; - handleInputChange: NodeObjectInputTreeProps["handleInputChange"]; - handleInputClick: NodeObjectInputTreeProps["handleInputClick"]; - className?: string; - displayName?: string; -}> = ({ - selfKey, - schema, - entries, - errors, - handleInputChange, - handleInputClick, - className, - displayName, -}) => { - entries ??= schema.default ?? []; - return ( -
- {displayName && {displayName}} - {entries.map((entry: string, index: number) => { - const entryKey = `${selfKey}[${index}]`; - return ( -
-
- {schema.items - ? - : - } - -
- {errors[entryKey] && - {errors[entryKey]} - } -
- ) - })} - - {errors[selfKey] && {errors[selfKey]}} -
- ); - }; - -const NodeStringInput: FC<{ - selfKey: string; - schema: BlockIOStringSubSchema; - value?: string; - error?: string; - handleInputChange: NodeObjectInputTreeProps["handleInputChange"]; - handleInputClick: NodeObjectInputTreeProps["handleInputClick"]; - className?: string; - displayName: string; -}> = ({ - selfKey, - schema, - value, - error, - handleInputChange, - handleInputClick, - className, - displayName, -}) => { - return ( -
- {schema.enum ? ( - - ) : ( -
- handleInputChange(selfKey, e.target.value)} - className="pr-8" - /> - -
- )} - {error && {error}} -
- ); - }; - -const NodeNumberInput: FC<{ - selfKey: string; - schema: BlockIONumberSubSchema; - value?: number; - error?: string; - handleInputChange: NodeObjectInputTreeProps["handleInputChange"]; - className?: string; - displayName?: string; -}> = ({ selfKey, schema, value, error, handleInputChange, className, displayName }) => { - value ??= schema.default; - return ( -
-
- {displayName && } - handleInputChange(selfKey, parseFloat(e.target.value))} - /> -
- {error && {error}} -
- ); -}; - -const NodeBooleanInput: FC<{ - selfKey: string; - schema: BlockIOBooleanSubSchema; - value?: boolean; - error?: string; - handleInputChange: NodeObjectInputTreeProps["handleInputChange"]; - className?: string; - displayName: string; -}> = ({ selfKey, schema, value, error, handleInputChange, className, displayName }) => { - value ??= schema.default ?? false; - return ( -
-
- handleInputChange(selfKey, v)} /> - {displayName} -
- {error && {error}} -
- ); -}; - -const NodeFallbackInput: FC<{ - selfKey: string; - schema?: BlockIOSubSchema; - value: any; - error?: string; - handleInputClick: NodeObjectInputTreeProps["handleInputClick"]; - className?: string; - displayName: string; -}> = ({ selfKey, schema, value, error, handleInputClick, className, displayName }) => { - return ( -
- handleInputClick(selfKey)} - value={value} - placeholder={ - schema?.placeholder || `Enter ${beautifyString(displayName)} (Complex)` - } - /> - {error && {error}} -
- ); -}; - -const ClickableInput: FC<{ - handleInputClick: () => void; - value?: string; - secret?: boolean; - placeholder?: string; - className?: string; -}> = ({ - handleInputClick, - value = "", - placeholder = "", - secret = false, - className, -}) => ( -
- {secret - ? {value ? "********" : placeholder} - : value || {placeholder} - } -
- ); diff --git a/rnd/autogpt_builder/src/components/ui/select.tsx b/rnd/autogpt_builder/src/components/ui/select.tsx deleted file mode 100644 index 1fa9cca408d8..000000000000 --- a/rnd/autogpt_builder/src/components/ui/select.tsx +++ /dev/null @@ -1,164 +0,0 @@ -"use client" - -import * as React from "react" -import { - CaretSortIcon, - CheckIcon, - ChevronDownIcon, - ChevronUpIcon, -} from "@radix-ui/react-icons" -import * as SelectPrimitive from "@radix-ui/react-select" - -import { cn } from "@/lib/utils" - -const Select = SelectPrimitive.Root - -const SelectGroup = SelectPrimitive.Group - -const SelectValue = SelectPrimitive.Value - -const SelectTrigger = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - span]:line-clamp-1 dark:border-neutral-800 dark:ring-offset-neutral-950 dark:placeholder:text-neutral-400 dark:focus:ring-neutral-300", - className - )} - {...props} - > - {children} - - - - -)) -SelectTrigger.displayName = SelectPrimitive.Trigger.displayName - -const SelectScrollUpButton = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - -)) -SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName - -const SelectScrollDownButton = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - - - -)) -SelectScrollDownButton.displayName = - SelectPrimitive.ScrollDownButton.displayName - -const SelectContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, position = "popper", ...props }, ref) => ( - - - - - {children} - - - - -)) -SelectContent.displayName = SelectPrimitive.Content.displayName - -const SelectLabel = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -SelectLabel.displayName = SelectPrimitive.Label.displayName - -const SelectItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - - - - - - {children} - -)) -SelectItem.displayName = SelectPrimitive.Item.displayName - -const SelectSeparator = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -SelectSeparator.displayName = SelectPrimitive.Separator.displayName - -export { - Select, - SelectGroup, - SelectValue, - SelectTrigger, - SelectContent, - SelectLabel, - SelectItem, - SelectSeparator, - SelectScrollUpButton, - SelectScrollDownButton, -} diff --git a/rnd/autogpt_builder/src/lib/autogpt-server-api/types.ts b/rnd/autogpt_builder/src/lib/autogpt-server-api/types.ts index acc4e1745fb4..20551536e344 100644 --- a/rnd/autogpt_builder/src/lib/autogpt-server-api/types.ts +++ b/rnd/autogpt_builder/src/lib/autogpt-server-api/types.ts @@ -9,80 +9,51 @@ export type Block = { export type BlockIORootSchema = { type: "object"; - properties: { [key: string]: BlockIOSubSchema }; + properties: { [key: string]: BlockIOSchema }; required?: string[]; + additionalProperties?: { type: string }; } -export type BlockIOSubSchema = - | BlockIOSimpleTypeSubSchema - | BlockIOCombinedTypeSubSchema; - -type BlockIOSimpleTypeSubSchema = - | BlockIOObjectSubSchema - | BlockIOKVSubSchema - | BlockIOArraySubSchema - | BlockIOStringSubSchema - | BlockIONumberSubSchema - | BlockIOBooleanSubSchema - | BlockIONullSubSchema; - -type BlockIOSubSchemaMeta = { +export type BlockIOSchema = { title?: string; description?: string; placeholder?: string; -}; - -export type BlockIOObjectSubSchema = BlockIOSubSchemaMeta & { - type: "object"; - properties: { [key: string]: BlockIOSubSchema }; - default?: { [key: keyof BlockIOObjectSubSchema["properties"]]: any }; - required?: keyof BlockIOObjectSubSchema["properties"][]; -}; +} & (BlockIOSimpleTypeSchema | BlockIOCombinedTypeSchema); -export type BlockIOKVSubSchema = BlockIOSubSchemaMeta & { +type BlockIOSimpleTypeSchema = { type: "object"; - additionalProperties: { type: "string" | "number" | "integer" }; - default?: { [key: string]: string | number }; -}; - -export type BlockIOArraySubSchema = BlockIOSubSchemaMeta & { + properties: { [key: string]: BlockIOSchema }; + required?: string[]; + additionalProperties?: { type: string }; +} | { type: "array"; - items?: BlockIOSimpleTypeSubSchema; - default?: Array; -}; - -export type BlockIOStringSubSchema = BlockIOSubSchemaMeta & { + items?: BlockIOSimpleTypeSchema; +} | { type: "string"; enum?: string[]; secret?: true; default?: string; -}; - -export type BlockIONumberSubSchema = BlockIOSubSchemaMeta & { +} | { type: "integer" | "number"; default?: number; -}; - -export type BlockIOBooleanSubSchema = BlockIOSubSchemaMeta & { +} | { type: "boolean"; default?: boolean; -}; - -export type BlockIONullSubSchema = BlockIOSubSchemaMeta & { +} | { type: "null"; }; // At the time of writing, combined schemas only occur on the first nested level in a // block schema. It is typed this way to make the use of these objects less tedious. -type BlockIOCombinedTypeSubSchema = BlockIOSubSchemaMeta & ({ - allOf: [BlockIOSimpleTypeSubSchema]; +type BlockIOCombinedTypeSchema = { + allOf: [BlockIOSimpleTypeSchema]; } | { - anyOf: BlockIOSimpleTypeSubSchema[]; + anyOf: BlockIOSimpleTypeSchema[]; default?: string | number | boolean | null; } | { - oneOf: BlockIOSimpleTypeSubSchema[]; + oneOf: BlockIOSimpleTypeSchema[]; default?: string | number | boolean | null; -}); +}; /* Mirror of autogpt_server/data/graph.py:Node */ export type Node = { diff --git a/rnd/autogpt_builder/src/lib/utils.ts b/rnd/autogpt_builder/src/lib/utils.ts index 66105588d54d..a8968085d1a9 100644 --- a/rnd/autogpt_builder/src/lib/utils.ts +++ b/rnd/autogpt_builder/src/lib/utils.ts @@ -41,7 +41,6 @@ export function getTypeTextColor(type: string | null): string { array: 'text-indigo-500', null: 'text-gray-500', '': 'text-gray-500', - any: 'text-gray-500', }[type] || 'text-gray-500'; } @@ -56,7 +55,6 @@ export function getTypeBgColor(type: string | null): string { array: 'bg-indigo-500', null: 'bg-gray-500', '': 'bg-gray-500', - any: 'bg-gray-500', }[type] || 'bg-gray-500'; } @@ -70,7 +68,6 @@ export function getTypeColor(type: string | null): string { array: '#6366f1', null: '#6b7280', '': '#6b7280', - any: '#6b7280', }[type] || '#6b7280'; } diff --git a/rnd/autogpt_builder/yarn.lock b/rnd/autogpt_builder/yarn.lock index 1bcabe041d31..e66cff719206 100644 --- a/rnd/autogpt_builder/yarn.lock +++ b/rnd/autogpt_builder/yarn.lock @@ -224,11 +224,6 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== -"@radix-ui/number@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.1.0.tgz#1e95610461a09cdf8bb05c152e76ca1278d5da46" - integrity sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ== - "@radix-ui/primitive@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.0.tgz#42ef83b3b56dccad5d703ae8c42919a68798bbe2" @@ -452,33 +447,6 @@ "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-use-controllable-state" "1.1.0" -"@radix-ui/react-select@^2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-select/-/react-select-2.1.1.tgz#df05cb0b29d3deaef83b505917c4042e0e418a9f" - integrity sha512-8iRDfyLtzxlprOo9IicnzvpsO1wNCkuwzzCM+Z5Rb5tNOpCdMvcc2AkzX0Fz+Tz9v6NJ5B/7EEgyZveo4FBRfQ== - dependencies: - "@radix-ui/number" "1.1.0" - "@radix-ui/primitive" "1.1.0" - "@radix-ui/react-collection" "1.1.0" - "@radix-ui/react-compose-refs" "1.1.0" - "@radix-ui/react-context" "1.1.0" - "@radix-ui/react-direction" "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-popper" "1.2.0" - "@radix-ui/react-portal" "1.1.1" - "@radix-ui/react-primitive" "2.0.0" - "@radix-ui/react-slot" "1.1.0" - "@radix-ui/react-use-callback-ref" "1.1.0" - "@radix-ui/react-use-controllable-state" "1.1.0" - "@radix-ui/react-use-layout-effect" "1.1.0" - "@radix-ui/react-use-previous" "1.1.0" - "@radix-ui/react-visually-hidden" "1.1.0" - aria-hidden "^1.1.1" - react-remove-scroll "2.5.7" - "@radix-ui/react-slot@1.1.0", "@radix-ui/react-slot@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.0.tgz#7c5e48c36ef5496d97b08f1357bb26ed7c714b84" diff --git a/rnd/autogpt_server/.env.template b/rnd/autogpt_server/.env.template index 429b922b196c..8b1ce0ee8f56 100644 --- a/rnd/autogpt_server/.env.template +++ b/rnd/autogpt_server/.env.template @@ -8,3 +8,6 @@ REDDIT_CLIENT_ID= REDDIT_CLIENT_SECRET= REDDIT_USERNAME= REDDIT_PASSWORD= + +# Discord +DISCORD_BOT_TOKEN= \ No newline at end of file diff --git a/rnd/autogpt_server/autogpt_server/blocks/basic.py b/rnd/autogpt_server/autogpt_server/blocks/basic.py index 6077914dcf29..4e84c2f1f15e 100644 --- a/rnd/autogpt_server/autogpt_server/blocks/basic.py +++ b/rnd/autogpt_server/autogpt_server/blocks/basic.py @@ -1,9 +1,10 @@ from abc import ABC, abstractmethod -from typing import Any, Generic, TypeVar +from typing import Any, Generic, List, TypeVar from pydantic import Field from autogpt_server.data.block import Block, BlockCategory, BlockOutput, BlockSchema +from autogpt_server.data.model import SchemaField from autogpt_server.util.mock import MockObject @@ -181,3 +182,138 @@ def __init__(self): def block_id(self) -> str: return "363ae599-353e-4804-937e-b2ee3cef3da4" + + +class DictionaryAddEntryBlock(Block): + class Input(BlockSchema): + dictionary: dict | None = SchemaField( + default=None, + description="The dictionary to add the entry to. If not provided, a new dictionary will be created.", + placeholder='{"key1": "value1", "key2": "value2"}', + ) + key: str = SchemaField( + description="The key for the new entry.", placeholder="new_key" + ) + value: Any = SchemaField( + description="The value for the new entry.", placeholder="new_value" + ) + + class Output(BlockSchema): + updated_dictionary: dict = SchemaField( + description="The dictionary with the new entry added." + ) + error: str = SchemaField(description="Error message if the operation failed.") + + def __init__(self): + super().__init__( + id="31d1064e-7446-4693-a7d4-65e5ca1180d1", + description="Adds a new key-value pair to a dictionary. If no dictionary is provided, a new one is created.", + categories={BlockCategory.BASIC}, + input_schema=DictionaryAddEntryBlock.Input, + output_schema=DictionaryAddEntryBlock.Output, + test_input=[ + { + "dictionary": {"existing_key": "existing_value"}, + "key": "new_key", + "value": "new_value", + }, + {"key": "first_key", "value": "first_value"}, + ], + test_output=[ + ( + "updated_dictionary", + {"existing_key": "existing_value", "new_key": "new_value"}, + ), + ("updated_dictionary", {"first_key": "first_value"}), + ], + ) + + def run(self, input_data: Input) -> BlockOutput: + try: + # If no dictionary is provided, create a new one + if input_data.dictionary is None: + updated_dict = {} + else: + # Create a copy of the input dictionary to avoid modifying the original + updated_dict = input_data.dictionary.copy() + + # Add the new key-value pair + updated_dict[input_data.key] = input_data.value + + yield "updated_dictionary", updated_dict + except Exception as e: + yield "error", f"Failed to add entry to dictionary: {str(e)}" + + +class ListAddEntryBlock(Block): + class Input(BlockSchema): + list: List[Any] | None = SchemaField( + default=None, + description="The list to add the entry to. If not provided, a new list will be created.", + placeholder='[1, "string", {"key": "value"}]', + ) + entry: Any = SchemaField( + description="The entry to add to the list. Can be of any type (string, int, dict, etc.).", + placeholder='{"new_key": "new_value"}', + ) + position: int | None = SchemaField( + default=None, + description="The position to insert the new entry. If not provided, the entry will be appended to the end of the list.", + placeholder="0", + ) + + class Output(BlockSchema): + updated_list: List[Any] = SchemaField( + description="The list with the new entry added." + ) + error: str = SchemaField(description="Error message if the operation failed.") + + def __init__(self): + super().__init__( + id="aeb08fc1-2fc1-4141-bc8e-f758f183a822", + description="Adds a new entry to a list. The entry can be of any type. If no list is provided, a new one is created.", + categories={BlockCategory.BASIC}, + input_schema=ListAddEntryBlock.Input, + output_schema=ListAddEntryBlock.Output, + test_input=[ + { + "list": [1, "string", {"existing_key": "existing_value"}], + "entry": {"new_key": "new_value"}, + "position": 1, + }, + {"entry": "first_entry"}, + {"list": ["a", "b", "c"], "entry": "d"}, + ], + test_output=[ + ( + "updated_list", + [ + 1, + {"new_key": "new_value"}, + "string", + {"existing_key": "existing_value"}, + ], + ), + ("updated_list", ["first_entry"]), + ("updated_list", ["a", "b", "c", "d"]), + ], + ) + + def run(self, input_data: Input) -> BlockOutput: + try: + # If no list is provided, create a new one + if input_data.list is None: + updated_list = [] + else: + # Create a copy of the input list to avoid modifying the original + updated_list = input_data.list.copy() + + # Add the new entry + if input_data.position is None: + updated_list.append(input_data.entry) + else: + updated_list.insert(input_data.position, input_data.entry) + + yield "updated_list", updated_list + except Exception as e: + yield "error", f"Failed to add entry to list: {str(e)}" diff --git a/rnd/autogpt_server/autogpt_server/blocks/discordblock.py b/rnd/autogpt_server/autogpt_server/blocks/discordblock.py new file mode 100644 index 000000000000..5f8a5b980089 --- /dev/null +++ b/rnd/autogpt_server/autogpt_server/blocks/discordblock.py @@ -0,0 +1,205 @@ +import asyncio + +import aiohttp +import discord +from pydantic import Field + +from autogpt_server.data.block import Block, BlockOutput, BlockSchema +from autogpt_server.data.model import BlockSecret, SecretField + + +class DiscordReaderBlock(Block): + class Input(BlockSchema): + discord_bot_token: BlockSecret = SecretField( + key="discord_bot_token", description="Discord bot token" + ) + + class Output(BlockSchema): + message_content: str = Field(description="The content of the message received") + channel_name: str = Field( + description="The name of the channel the message was received from" + ) + username: str = Field( + description="The username of the user who sent the message" + ) + + def __init__(self): + super().__init__( + id="d3f4g5h6-1i2j-3k4l-5m6n-7o8p9q0r1s2t", # Unique ID for the node + input_schema=DiscordReaderBlock.Input, # Assign input schema + output_schema=DiscordReaderBlock.Output, # Assign output schema + test_input={"discord_bot_token": "test_token"}, + test_output=[ + ( + "message_content", + "Hello!\n\nFile from user: example.txt\nContent: This is the content of the file.", + ), + ("channel_name", "general"), + ("username", "test_user"), + ], + test_mock={ + "run_bot": lambda token: asyncio.Future() # Create a Future object for mocking + }, + ) + + async def run_bot(self, token: str): + intents = discord.Intents.default() + intents.message_content = True + + client = discord.Client(intents=intents) + + self.output_data = None + self.channel_name = None + self.username = None + + @client.event + async def on_ready(): + print(f"Logged in as {client.user}") + + @client.event + async def on_message(message): + if message.author == client.user: + return + + self.output_data = message.content + self.channel_name = message.channel.name + self.username = message.author.name + + if message.attachments: + attachment = message.attachments[0] # Process the first attachment + if attachment.filename.endswith((".txt", ".py")): + async with aiohttp.ClientSession() as session: + async with session.get(attachment.url) as response: + file_content = await response.text() + self.output_data += f"\n\nFile from user: {attachment.filename}\nContent: {file_content}" + + await client.close() + + await client.start(token) + + def run(self, input_data: "DiscordReaderBlock.Input") -> BlockOutput: + try: + loop = asyncio.get_event_loop() + future = self.run_bot(input_data.discord_bot_token.get_secret_value()) + + # If it's a Future (mock), set the result + if isinstance(future, asyncio.Future): + future.set_result( + { + "output_data": "Hello!\n\nFile from user: example.txt\nContent: This is the content of the file.", + "channel_name": "general", + "username": "test_user", + } + ) + + result = loop.run_until_complete(future) + + # For testing purposes, use the mocked result + if isinstance(result, dict): + self.output_data = result.get("output_data") + self.channel_name = result.get("channel_name") + self.username = result.get("username") + + if ( + self.output_data is None + or self.channel_name is None + or self.username is None + ): + raise ValueError("No message, channel name, or username received.") + + yield "message_content", self.output_data + yield "channel_name", self.channel_name + yield "username", self.username + + except discord.errors.LoginFailure as login_err: + raise ValueError(f"Login error occurred: {login_err}") + except Exception as e: + raise ValueError(f"An error occurred: {e}") + + +class DiscordMessageSenderBlock(Block): + class Input(BlockSchema): + discord_bot_token: BlockSecret = SecretField( + key="discord_bot_token", description="Discord bot token" + ) + message_content: str = Field(description="The content of the message received") + channel_name: str = Field( + description="The name of the channel the message was received from" + ) + + class Output(BlockSchema): + status: str = Field( + description="The status of the operation (e.g., 'Message sent', 'Error')" + ) + + def __init__(self): + super().__init__( + id="h1i2j3k4-5l6m-7n8o-9p0q-r1s2t3u4v5w6", # Unique ID for the node + input_schema=DiscordMessageSenderBlock.Input, # Assign input schema + output_schema=DiscordMessageSenderBlock.Output, # Assign output schema + test_input={ + "discord_bot_token": "YOUR_DISCORD_BOT_TOKEN", + "channel_name": "general", + "message_content": "Hello, Discord!", + }, + test_output=[("status", "Message sent")], + test_mock={ + "send_message": lambda token, channel_name, message_content: asyncio.Future() + }, + ) + + async def send_message(self, token: str, channel_name: str, message_content: str): + intents = discord.Intents.default() + intents.guilds = True # Required for fetching guild/channel information + client = discord.Client(intents=intents) + + @client.event + async def on_ready(): + print(f"Logged in as {client.user}") + for guild in client.guilds: + for channel in guild.text_channels: + if channel.name == channel_name: + # Split message into chunks if it exceeds 2000 characters + for chunk in self.chunk_message(message_content): + await channel.send(chunk) + self.output_data = "Message sent" + await client.close() + return + + self.output_data = "Channel not found" + await client.close() + + await client.start(token) + + def chunk_message(self, message: str, limit: int = 2000) -> list: + """Splits a message into chunks not exceeding the Discord limit.""" + return [message[i : i + limit] for i in range(0, len(message), limit)] + + def run(self, input_data: "DiscordMessageSenderBlock.Input") -> BlockOutput: + try: + loop = asyncio.get_event_loop() + future = self.send_message( + input_data.discord_bot_token.get_secret_value(), + input_data.channel_name, + input_data.message_content, + ) + + # If it's a Future (mock), set the result + if isinstance(future, asyncio.Future): + future.set_result("Message sent") + + result = loop.run_until_complete(future) + + # For testing purposes, use the mocked result + if isinstance(result, str): + self.output_data = result + + if self.output_data is None: + raise ValueError("No status message received.") + + yield "status", self.output_data + + except discord.errors.LoginFailure as login_err: + raise ValueError(f"Login error occurred: {login_err}") + except Exception as e: + raise ValueError(f"An error occurred: {e}") diff --git a/rnd/autogpt_server/autogpt_server/blocks/text.py b/rnd/autogpt_server/autogpt_server/blocks/text.py index 759995371c51..22299e4c81bd 100644 --- a/rnd/autogpt_server/autogpt_server/blocks/text.py +++ b/rnd/autogpt_server/autogpt_server/blocks/text.py @@ -154,3 +154,33 @@ def run(self, input_data: Input) -> BlockOutput: texts=input_data.texts, **input_data.named_texts, ) + + +class TextCombinerBlock(Block): + class Input(BlockSchema): + input1: str = Field(description="First text input", default="a") + input2: str = Field(description="Second text input", default="b") + + class Output(BlockSchema): + output: str = Field(description="Combined text") + + def __init__(self): + super().__init__( + id="e30a4d42-7b7d-4e6a-b36e-1f9b8e3b7d85", + description="This block combines multiple input texts into a single output text.", + categories={BlockCategory.TEXT}, + input_schema=TextCombinerBlock.Input, + output_schema=TextCombinerBlock.Output, + test_input=[ + {"input1": "Hello world I like ", "input2": "cake and to go for walks"}, + {"input1": "This is a test. ", "input2": "Let's see how it works."}, + ], + test_output=[ + ("output", "Hello world I like cake and to go for walks"), + ("output", "This is a test. Let's see how it works."), + ], + ) + + def run(self, input_data: Input) -> BlockOutput: + combined_text = (input_data.input1 or "") + (input_data.input2 or "") + yield "output", combined_text diff --git a/rnd/autogpt_server/autogpt_server/util/settings.py b/rnd/autogpt_server/autogpt_server/util/settings.py index b9be013113e9..d9515bbf7b66 100644 --- a/rnd/autogpt_server/autogpt_server/util/settings.py +++ b/rnd/autogpt_server/autogpt_server/util/settings.py @@ -105,6 +105,8 @@ class Secrets(UpdateTrackingModel["Secrets"], BaseSettings): medium_api_key: str = Field(default="", description="Medium API key") medium_author_id: str = Field(default="", description="Medium author ID") + discord_bot_token: str = Field(default="", description="Discord bot token") + # Add more secret fields as needed model_config = SettingsConfigDict( diff --git a/rnd/autogpt_server/poetry.lock b/rnd/autogpt_server/poetry.lock index 3df327fdfa0f..ffb7d270b40b 100644 --- a/rnd/autogpt_server/poetry.lock +++ b/rnd/autogpt_server/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "agpt" @@ -25,7 +25,7 @@ requests = "*" sentry-sdk = "^1.40.4" [package.extras] -benchmark = ["agbenchmark @ file:///Users/aarushi/autogpt/AutoGPT/benchmark"] +benchmark = ["agbenchmark @ file:///home/bently/Desktop/autogpt-ui/AutoGPT/benchmark"] [package.source] type = "directory" @@ -329,7 +329,7 @@ watchdog = "4.0.0" webdriver-manager = "^4.0.1" [package.extras] -benchmark = ["agbenchmark @ file:///Users/aarushi/autogpt/AutoGPT/benchmark"] +benchmark = ["agbenchmark @ file:///home/bently/Desktop/autogpt-ui/AutoGPT/benchmark"] [package.source] type = "directory" @@ -1073,6 +1073,26 @@ wrapt = ">=1.10,<2" [package.extras] dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] +[[package]] +name = "discord-py" +version = "2.4.0" +description = "A Python wrapper for the Discord API" +optional = false +python-versions = ">=3.8" +files = [ + {file = "discord.py-2.4.0-py3-none-any.whl", hash = "sha256:b8af6711c70f7e62160bfbecb55be699b5cb69d007426759ab8ab06b1bd77d1d"}, + {file = "discord_py-2.4.0.tar.gz", hash = "sha256:d07cb2a223a185873a1d0ee78b9faa9597e45b3f6186df21a95cec1e9bcdc9a5"}, +] + +[package.dependencies] +aiohttp = ">=3.7.4,<4" + +[package.extras] +docs = ["sphinx (==4.4.0)", "sphinx-inline-tabs (==2023.4.21)", "sphinxcontrib-applehelp (==1.0.4)", "sphinxcontrib-devhelp (==1.0.2)", "sphinxcontrib-htmlhelp (==2.0.1)", "sphinxcontrib-jsmath (==1.0.1)", "sphinxcontrib-qthelp (==1.0.3)", "sphinxcontrib-serializinghtml (==1.1.5)", "sphinxcontrib-trio (==1.1.2)", "sphinxcontrib-websupport (==1.2.4)", "typing-extensions (>=4.3,<5)"] +speed = ["Brotli", "aiodns (>=1.1)", "cchardet (==2.1.7)", "orjson (>=3.5.4)"] +test = ["coverage[toml]", "pytest", "pytest-asyncio", "pytest-cov", "pytest-mock", "typing-extensions (>=4.3,<5)", "tzdata"] +voice = ["PyNaCl (>=1.3.0,<1.6)"] + [[package]] name = "distro" version = "1.9.0" @@ -6399,4 +6419,4 @@ test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "b9a68db94e5721bfc916e583626e6da66a3469451d179bf9ee117d0a31b865f2" +content-hash = "9991857e7076d3bfcbae7af6c2cec54dc943167a3adceb5a0ebf74d80c05778f" diff --git a/rnd/autogpt_server/pyproject.toml b/rnd/autogpt_server/pyproject.toml index 8fa8202af6fd..a94e188a0824 100644 --- a/rnd/autogpt_server/pyproject.toml +++ b/rnd/autogpt_server/pyproject.toml @@ -39,6 +39,7 @@ ollama = "^0.3.0" feedparser = "^6.0.11" python-dotenv = "^1.0.1" expiringdict = "^1.2.2" +discord-py = "^2.4.0" autogpt-libs = { path = "../autogpt_libs", develop = true } [tool.poetry.group.dev.dependencies]