mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-01-10 23:58:06 -05:00
Merge branch 'master' of github.com:Significant-Gravitas/AutoGPT into swiftyos/secrt-900-update-block-ui
This commit is contained in:
@@ -88,7 +88,7 @@ class FindInDictionaryBlock(Block):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="b2g2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6",
|
||||
id="0e50422c-6dee-4145-83d6-3a5a392f65de",
|
||||
description="Lookup the given key in the input dictionary/object/list and return the value.",
|
||||
input_schema=FindInDictionaryBlock.Input,
|
||||
output_schema=FindInDictionaryBlock.Output,
|
||||
@@ -429,7 +429,7 @@ class NoteBlock(Block):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="31d1064e-7446-4693-o7d4-65e5ca9110d1",
|
||||
id="cc10ff7b-7753-4ff2-9af6-9399b1a7eddc",
|
||||
description="This block is used to display a sticky note with the given text.",
|
||||
categories={BlockCategory.BASIC},
|
||||
input_schema=NoteBlock.Input,
|
||||
|
||||
42
autogpt_platform/backend/backend/blocks/decoder_block.py
Normal file
42
autogpt_platform/backend/backend/blocks/decoder_block.py
Normal file
@@ -0,0 +1,42 @@
|
||||
import codecs
|
||||
|
||||
from backend.data.block import Block, BlockCategory, BlockOutput, BlockSchema
|
||||
from backend.data.model import SchemaField
|
||||
|
||||
|
||||
class TextDecoderBlock(Block):
|
||||
class Input(BlockSchema):
|
||||
text: str = SchemaField(
|
||||
description="A string containing escaped characters to be decoded",
|
||||
placeholder='Your entire text block with \\n and \\" escaped characters',
|
||||
)
|
||||
|
||||
class Output(BlockSchema):
|
||||
decoded_text: str = SchemaField(
|
||||
description="The decoded text with escape sequences processed"
|
||||
)
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="2570e8fe-8447-43ed-84c7-70d657923231",
|
||||
description="Decodes a string containing escape sequences into actual text",
|
||||
categories={BlockCategory.TEXT},
|
||||
input_schema=TextDecoderBlock.Input,
|
||||
output_schema=TextDecoderBlock.Output,
|
||||
test_input={"text": """Hello\nWorld!\nThis is a \"quoted\" string."""},
|
||||
test_output=[
|
||||
(
|
||||
"decoded_text",
|
||||
"""Hello
|
||||
World!
|
||||
This is a "quoted" string.""",
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
def run(self, input_data: Input, **kwargs) -> BlockOutput:
|
||||
try:
|
||||
decoded_text = codecs.decode(input_data.text, "unicode_escape")
|
||||
yield "decoded_text", decoded_text
|
||||
except Exception as e:
|
||||
yield "error", f"Error decoding text: {str(e)}"
|
||||
@@ -28,7 +28,7 @@ class ReadDiscordMessagesBlock(Block):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="d3f4g5h6-1i2j-3k4l-5m6n-7o8p9q0r1s2t", # Unique ID for the node
|
||||
id="df06086a-d5ac-4abb-9996-2ad0acb2eff7",
|
||||
input_schema=ReadDiscordMessagesBlock.Input, # Assign input schema
|
||||
output_schema=ReadDiscordMessagesBlock.Output, # Assign output schema
|
||||
description="Reads messages from a Discord channel using a bot token.",
|
||||
@@ -146,7 +146,7 @@ class SendDiscordMessageBlock(Block):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="h1i2j3k4-5l6m-7n8o-9p0q-r1s2t3u4v5w6", # Unique ID for the node
|
||||
id="d0822ab5-9f8a-44a3-8971-531dd0178b6b",
|
||||
input_schema=SendDiscordMessageBlock.Input, # Assign input schema
|
||||
output_schema=SendDiscordMessageBlock.Output, # Assign output schema
|
||||
description="Sends a message to a Discord channel using a bot token.",
|
||||
|
||||
@@ -43,7 +43,7 @@ class SendEmailBlock(Block):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="a1234567-89ab-cdef-0123-456789abcdef",
|
||||
id="4335878a-394e-4e67-adf2-919877ff49ae",
|
||||
description="This block sends an email using the provided SMTP credentials.",
|
||||
categories={BlockCategory.OUTPUT},
|
||||
input_schema=SendEmailBlock.Input,
|
||||
|
||||
@@ -19,7 +19,7 @@ class StepThroughItemsBlock(Block):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="f8e7d6c5-b4a3-2c1d-0e9f-8g7h6i5j4k3l",
|
||||
id="f66a3543-28d3-4ab5-8945-9b336371e2ce",
|
||||
input_schema=StepThroughItemsBlock.Input,
|
||||
output_schema=StepThroughItemsBlock.Output,
|
||||
categories={BlockCategory.LOGIC},
|
||||
|
||||
@@ -392,7 +392,7 @@ class AITextSummarizerBlock(Block):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="c3d4e5f6-7g8h-9i0j-1k2l-m3n4o5p6q7r8",
|
||||
id="a0a69be1-4528-491c-a85a-a4ab6873e3f0",
|
||||
description="Utilize a Large Language Model (LLM) to summarize a long text.",
|
||||
categories={BlockCategory.AI, BlockCategory.TEXT},
|
||||
input_schema=AITextSummarizerBlock.Input,
|
||||
@@ -535,7 +535,7 @@ class AIConversationBlock(Block):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="c3d4e5f6-g7h8-i9j0-k1l2-m3n4o5p6q7r8",
|
||||
id="32a87eab-381e-4dd4-bdb8-4c47151be35a",
|
||||
description="Advanced LLM call that takes a list of messages and sends them to the language model.",
|
||||
categories={BlockCategory.AI},
|
||||
input_schema=AIConversationBlock.Input,
|
||||
|
||||
@@ -43,7 +43,7 @@ class ReadRSSFeedBlock(Block):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="c6731acb-4105-4zp1-bc9b-03d0036h370g",
|
||||
id="5ebe6768-8e5d-41e3-9134-1c7bd89a8d52",
|
||||
input_schema=ReadRSSFeedBlock.Input,
|
||||
output_schema=ReadRSSFeedBlock.Output,
|
||||
description="Reads RSS feed entries from a given URL.",
|
||||
|
||||
@@ -25,7 +25,7 @@ class GetWikipediaSummaryBlock(Block, GetRequest):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="h5e7f8g9-1b2c-3d4e-5f6g-7h8i9j0k1l2m",
|
||||
id="f5b0f5d0-1862-4d61-94be-3ad0fa772760",
|
||||
description="This block fetches the summary of a given topic from Wikipedia.",
|
||||
categories={BlockCategory.SEARCH},
|
||||
input_schema=GetWikipediaSummaryBlock.Input,
|
||||
@@ -62,7 +62,7 @@ class SearchTheWebBlock(Block, GetRequest):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="b2c3d4e5-6f7g-8h9i-0j1k-l2m3n4o5p6q7",
|
||||
id="87840993-2053-44b7-8da4-187ad4ee518c",
|
||||
description="This block searches the internet for the given search query.",
|
||||
categories={BlockCategory.SEARCH},
|
||||
input_schema=SearchTheWebBlock.Input,
|
||||
@@ -109,7 +109,7 @@ class ExtractWebsiteContentBlock(Block, GetRequest):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="a1b2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6", # Unique ID for the block
|
||||
id="436c3984-57fd-4b85-8e9a-459b356883bd",
|
||||
description="This block scrapes the content from the given web URL.",
|
||||
categories={BlockCategory.SEARCH},
|
||||
input_schema=ExtractWebsiteContentBlock.Input,
|
||||
|
||||
@@ -77,7 +77,7 @@ class GetCurrentDateAndTimeBlock(Block):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
id="b29c1b50-5d0e-4d9f-8f9d-1b0e6fcbf0h2",
|
||||
id="716a67b3-6760-42e7-86dc-18645c6e00fc",
|
||||
description="This block outputs the current date and time.",
|
||||
categories={BlockCategory.TEXT},
|
||||
input_schema=GetCurrentDateAndTimeBlock.Input,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import asyncio
|
||||
import logging
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
import uvicorn
|
||||
from autogpt_libs.auth import parse_jwt_token
|
||||
@@ -16,7 +17,17 @@ from backend.util.settings import Config, Settings
|
||||
logger = logging.getLogger(__name__)
|
||||
settings = Settings()
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
await event_queue.connect()
|
||||
manager = get_connection_manager()
|
||||
asyncio.create_task(event_broadcaster(manager))
|
||||
yield
|
||||
await event_queue.close()
|
||||
|
||||
|
||||
app = FastAPI(lifespan=lifespan)
|
||||
event_queue = AsyncRedisEventQueue()
|
||||
_connection_manager = None
|
||||
|
||||
@@ -37,18 +48,6 @@ def get_connection_manager():
|
||||
return _connection_manager
|
||||
|
||||
|
||||
@app.on_event("startup")
|
||||
async def startup_event():
|
||||
await event_queue.connect()
|
||||
manager = get_connection_manager()
|
||||
asyncio.create_task(event_broadcaster(manager))
|
||||
|
||||
|
||||
@app.on_event("shutdown")
|
||||
async def shutdown_event():
|
||||
await event_queue.close()
|
||||
|
||||
|
||||
async def event_broadcaster(manager: ConnectionManager):
|
||||
while True:
|
||||
event = await event_queue.get()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import json
|
||||
from typing import Any, Type, TypeVar, get_origin
|
||||
from typing import Any, Type, TypeVar, get_args, get_origin
|
||||
|
||||
|
||||
class ConversionError(Exception):
|
||||
@@ -103,26 +103,75 @@ def __convert_bool(value: Any) -> bool:
|
||||
|
||||
|
||||
def convert(value: Any, target_type: Type):
|
||||
target_type = get_origin(target_type) or target_type
|
||||
if target_type not in [list, dict, tuple, str, set, int, float, bool]:
|
||||
origin = get_origin(target_type)
|
||||
args = get_args(target_type)
|
||||
if origin is None:
|
||||
origin = target_type
|
||||
if origin not in [list, dict, tuple, str, set, int, float, bool]:
|
||||
return value
|
||||
if isinstance(value, target_type):
|
||||
return value
|
||||
if target_type is list:
|
||||
return __convert_list(value)
|
||||
elif target_type is dict:
|
||||
return __convert_dict(value)
|
||||
elif target_type is tuple:
|
||||
return __convert_tuple(value)
|
||||
elif target_type is str:
|
||||
return __convert_str(value)
|
||||
elif target_type is set:
|
||||
return __convert_set(value)
|
||||
elif target_type is int:
|
||||
return __convert_num(value, int)
|
||||
elif target_type is float:
|
||||
return __convert_num(value, float)
|
||||
elif target_type is bool:
|
||||
return __convert_bool(value)
|
||||
|
||||
# Handle the case when value is already of the target type
|
||||
if isinstance(value, origin):
|
||||
if not args:
|
||||
return value
|
||||
else:
|
||||
# Need to convert elements
|
||||
if origin is list:
|
||||
return [convert(v, args[0]) for v in value]
|
||||
elif origin is tuple:
|
||||
# Tuples can have multiple types
|
||||
if len(args) == 1:
|
||||
return tuple(convert(v, args[0]) for v in value)
|
||||
else:
|
||||
return tuple(convert(v, t) for v, t in zip(value, args))
|
||||
elif origin is dict:
|
||||
key_type, val_type = args
|
||||
return {
|
||||
convert(k, key_type): convert(v, val_type) for k, v in value.items()
|
||||
}
|
||||
elif origin is set:
|
||||
return {convert(v, args[0]) for v in value}
|
||||
else:
|
||||
return value
|
||||
else:
|
||||
return value
|
||||
# Need to convert value to the origin type
|
||||
if origin is list:
|
||||
value = __convert_list(value)
|
||||
if args:
|
||||
return [convert(v, args[0]) for v in value]
|
||||
else:
|
||||
return value
|
||||
elif origin is dict:
|
||||
value = __convert_dict(value)
|
||||
if args:
|
||||
key_type, val_type = args
|
||||
return {
|
||||
convert(k, key_type): convert(v, val_type) for k, v in value.items()
|
||||
}
|
||||
else:
|
||||
return value
|
||||
elif origin is tuple:
|
||||
value = __convert_tuple(value)
|
||||
if args:
|
||||
if len(args) == 1:
|
||||
return tuple(convert(v, args[0]) for v in value)
|
||||
else:
|
||||
return tuple(convert(v, t) for v, t in zip(value, args))
|
||||
else:
|
||||
return value
|
||||
elif origin is str:
|
||||
return __convert_str(value)
|
||||
elif origin is set:
|
||||
value = __convert_set(value)
|
||||
if args:
|
||||
return {convert(v, args[0]) for v in value}
|
||||
else:
|
||||
return value
|
||||
elif origin is int:
|
||||
return __convert_num(value, int)
|
||||
elif origin is float:
|
||||
return __convert_num(value, float)
|
||||
elif origin is bool:
|
||||
return __convert_bool(value)
|
||||
else:
|
||||
return value
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"nodes": [
|
||||
{
|
||||
"id": "b8138bca-7892-42c2-9594-a845d3483413",
|
||||
"block_id": "d3f4g5h6-1i2j-3k4l-5m6n-7o8p9q0r1s2t",
|
||||
"block_id": "df06086a-d5ac-4abb-9996-2ad0acb2eff7",
|
||||
"input_default": {},
|
||||
"metadata": {
|
||||
"position": {
|
||||
@@ -59,7 +59,7 @@
|
||||
},
|
||||
{
|
||||
"id": "dda2d061-2ef9-4dc5-9433-918c8395a4ac",
|
||||
"block_id": "h1i2j3k4-5l6m-7n8o-9p0q-r1s2t3u4v5w6",
|
||||
"block_id": "d0822ab5-9f8a-44a3-8971-531dd0178b6b",
|
||||
"input_default": {},
|
||||
"metadata": {
|
||||
"position": {
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
},
|
||||
{
|
||||
"id": "b45cfa51-5ead-4621-9f1c-f847dfea3e4c",
|
||||
"block_id": "d3f4g5h6-1i2j-3k4l-5m6n-7o8p9q0r1s2t",
|
||||
"block_id": "df06086a-d5ac-4abb-9996-2ad0acb2eff7",
|
||||
"input_default": {},
|
||||
"metadata": {
|
||||
"position": {
|
||||
@@ -146,7 +146,7 @@
|
||||
},
|
||||
{
|
||||
"id": "8eedcf71-1146-4f54-b522-bf9b6e2d26b2",
|
||||
"block_id": "h1i2j3k4-5l6m-7n8o-9p0q-r1s2t3u4v5w6",
|
||||
"block_id": "d0822ab5-9f8a-44a3-8971-531dd0178b6b",
|
||||
"input_default": {},
|
||||
"metadata": {
|
||||
"position": {
|
||||
@@ -197,7 +197,7 @@
|
||||
},
|
||||
{
|
||||
"id": "a568daee-45d2-4429-bf33-cbe9e1261f7b",
|
||||
"block_id": "c3d4e5f6-g7h8-i9j0-k1l2-m3n4o5p6q7r8",
|
||||
"block_id": "32a87eab-381e-4dd4-bdb8-4c47151be35a",
|
||||
"input_default": {
|
||||
"model": "llama-3.1-70b-versatile",
|
||||
"max_tokens": 2000
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"nodes": [
|
||||
{
|
||||
"id": "60ba4aac-1751-4be7-8745-1bd32191d4a2",
|
||||
"block_id": "d3f4g5h6-1i2j-3k4l-5m6n-7o8p9q0r1s2t",
|
||||
"block_id": "df06086a-d5ac-4abb-9996-2ad0acb2eff7",
|
||||
"input_default": {},
|
||||
"metadata": {
|
||||
"position": {
|
||||
@@ -45,7 +45,7 @@
|
||||
},
|
||||
{
|
||||
"id": "5658c4f7-8e67-4d30-93f2-157bdbd3ef87",
|
||||
"block_id": "b2c3d4e5-6f7g-8h9i-0j1k-l2m3n4o5p6q7",
|
||||
"block_id": "87840993-2053-44b7-8da4-187ad4ee518c",
|
||||
"input_default": {},
|
||||
"metadata": {
|
||||
"position": {
|
||||
@@ -118,7 +118,7 @@
|
||||
},
|
||||
{
|
||||
"id": "f3d62f22-d193-4f04-85d2-164200fca4c0",
|
||||
"block_id": "h1i2j3k4-5l6m-7n8o-9p0q-r1s2t3u4v5w6",
|
||||
"block_id": "d0822ab5-9f8a-44a3-8971-531dd0178b6b",
|
||||
"input_default": {},
|
||||
"metadata": {
|
||||
"position": {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"nodes": [
|
||||
{
|
||||
"id": "382efac9-3def-4baf-b16a-d6d2512a5c8b",
|
||||
"block_id": "b2c3d4e5-6f7g-8h9i-0j1k-l2m3n4o5p6q7",
|
||||
"block_id": "87840993-2053-44b7-8da4-187ad4ee518c",
|
||||
"input_default": {
|
||||
"query": "19th July 2024 Microsoft Blackout"
|
||||
},
|
||||
@@ -44,7 +44,7 @@
|
||||
},
|
||||
{
|
||||
"id": "0cd8f670-8956-4942-ba28-aee732ec783f",
|
||||
"block_id": "b2g2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6",
|
||||
"block_id": "0e50422c-6dee-4145-83d6-3a5a392f65de",
|
||||
"input_default": {
|
||||
"key": "TITLE"
|
||||
},
|
||||
@@ -57,7 +57,7 @@
|
||||
},
|
||||
{
|
||||
"id": "4a15b6b9-036d-43d3-915a-7e931fbc6522",
|
||||
"block_id": "b2g2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6",
|
||||
"block_id": "0e50422c-6dee-4145-83d6-3a5a392f65de",
|
||||
"input_default": {
|
||||
"key": "CONTENT"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
-- Update AgentBlock IDs: this should cascade to the AgentNode and UserBlockCredit tables
|
||||
UPDATE "AgentBlock"
|
||||
SET "id" = CASE
|
||||
WHEN "id" = 'a1b2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6' THEN '436c3984-57fd-4b85-8e9a-459b356883bd'
|
||||
WHEN "id" = 'b2g2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6' THEN '0e50422c-6dee-4145-83d6-3a5a392f65de'
|
||||
WHEN "id" = 'c3d4e5f6-7g8h-9i0j-1k2l-m3n4o5p6q7r8' THEN 'a0a69be1-4528-491c-a85a-a4ab6873e3f0'
|
||||
WHEN "id" = 'c3d4e5f6-g7h8-i9j0-k1l2-m3n4o5p6q7r8' THEN '32a87eab-381e-4dd4-bdb8-4c47151be35a'
|
||||
WHEN "id" = 'b2c3d4e5-6f7g-8h9i-0j1k-l2m3n4o5p6q7' THEN '87840993-2053-44b7-8da4-187ad4ee518c'
|
||||
WHEN "id" = 'h1i2j3k4-5l6m-7n8o-9p0q-r1s2t3u4v5w6' THEN 'd0822ab5-9f8a-44a3-8971-531dd0178b6b'
|
||||
WHEN "id" = 'd3f4g5h6-1i2j-3k4l-5m6n-7o8p9q0r1s2t' THEN 'df06086a-d5ac-4abb-9996-2ad0acb2eff7'
|
||||
WHEN "id" = 'h5e7f8g9-1b2c-3d4e-5f6g-7h8i9j0k1l2m' THEN 'f5b0f5d0-1862-4d61-94be-3ad0fa772760'
|
||||
WHEN "id" = 'a1234567-89ab-cdef-0123-456789abcdef' THEN '4335878a-394e-4e67-adf2-919877ff49ae'
|
||||
WHEN "id" = 'f8e7d6c5-b4a3-2c1d-0e9f-8g7h6i5j4k3l' THEN 'f66a3543-28d3-4ab5-8945-9b336371e2ce'
|
||||
WHEN "id" = 'b29c1b50-5d0e-4d9f-8f9d-1b0e6fcbf0h2' THEN '716a67b3-6760-42e7-86dc-18645c6e00fc'
|
||||
WHEN "id" = '31d1064e-7446-4693-o7d4-65e5ca9110d1' THEN 'cc10ff7b-7753-4ff2-9af6-9399b1a7eddc'
|
||||
WHEN "id" = 'c6731acb-4105-4zp1-bc9b-03d0036h370g' THEN '5ebe6768-8e5d-41e3-9134-1c7bd89a8d52'
|
||||
ELSE "id"
|
||||
END;
|
||||
@@ -27,5 +27,6 @@ def test_type_conversion():
|
||||
|
||||
from typing import List
|
||||
|
||||
# assert convert("5", List[int]) == [5]
|
||||
assert convert("5", List[int]) == [5]
|
||||
assert convert("[5,4,2]", List[int]) == [5, 4, 2]
|
||||
assert convert([5, 4, 2], List[str]) == ["5", "4", "2"]
|
||||
|
||||
@@ -207,6 +207,7 @@ services:
|
||||
# - NEXT_PUBLIC_AGPT_SERVER_URL=http://localhost:8006/api
|
||||
# - NEXT_PUBLIC_AGPT_WS_SERVER_URL=ws://localhost:8001/ws
|
||||
# - NEXT_PUBLIC_AGPT_MARKETPLACE_URL=http://localhost:8015/api/v1/market
|
||||
# - NEXT_PUBLIC_BEHAVE_AS=LOCAL
|
||||
# ports:
|
||||
# - "3000:3000"
|
||||
# networks:
|
||||
|
||||
@@ -13,3 +13,6 @@ NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAic
|
||||
## Only used if you're using Supabase and OAuth
|
||||
AUTH_CALLBACK_URL=http://localhost:3000/auth/callback
|
||||
GA_MEASUREMENT_ID=G-FH2XK2W4GN
|
||||
|
||||
# When running locally, set NEXT_PUBLIC_BEHAVE_AS=CLOUD to use the a locally hosted marketplace (as is typical in development, and the cloud deployment), otherwise set it to LOCAL to have the marketplace open in a new tab
|
||||
NEXT_PUBLIC_BEHAVE_AS=LOCAL
|
||||
@@ -67,7 +67,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.47.1",
|
||||
"@types/node": "^20",
|
||||
"@types/node": "^22.7.3",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
"@types/react-modal": "^3.16.3",
|
||||
|
||||
@@ -6,8 +6,9 @@ import Image from "next/image";
|
||||
import getServerUser from "@/hooks/getServerUser";
|
||||
import ProfileDropdown from "./ProfileDropdown";
|
||||
import { IconCircleUser, IconMenu } from "@/components/ui/icons";
|
||||
import CreditButton from "@/components/CreditButton";
|
||||
import { NavBarButtons } from "./NavBarButtons";
|
||||
import CreditButton from "@/components/nav/CreditButton";
|
||||
|
||||
import { NavBarButtons } from "./nav/NavBarButtons";
|
||||
|
||||
export async function NavBar() {
|
||||
const isAvailable = Boolean(
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { BsBoxes } from "react-icons/bs";
|
||||
import { LuLaptop } from "react-icons/lu";
|
||||
import { LuShoppingCart } from "react-icons/lu";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { usePathname } from "next/navigation";
|
||||
|
||||
export function NavBarButtons({ className }: { className?: string }) {
|
||||
"use client";
|
||||
|
||||
const pathname = usePathname();
|
||||
const buttons = [
|
||||
{
|
||||
href: "/marketplace",
|
||||
text: "Marketplace",
|
||||
icon: <LuShoppingCart />,
|
||||
},
|
||||
{
|
||||
href: "/",
|
||||
text: "Monitor",
|
||||
icon: <LuLaptop />,
|
||||
},
|
||||
{
|
||||
href: "/build",
|
||||
text: "Build",
|
||||
icon: <BsBoxes />,
|
||||
},
|
||||
];
|
||||
|
||||
const activeButton = buttons.find((button) => button.href === pathname);
|
||||
|
||||
return buttons.map((button) => (
|
||||
<Link
|
||||
key={button.href}
|
||||
href={button.href}
|
||||
className={cn(
|
||||
className,
|
||||
"rounded-xl p-3",
|
||||
activeButton === button ? "button bg-gray-950 text-white" : "",
|
||||
)}
|
||||
>
|
||||
{button.icon} {button.text}
|
||||
</Link>
|
||||
));
|
||||
}
|
||||
@@ -33,6 +33,44 @@ const formSchema = z.object({
|
||||
importAsTemplate: z.boolean(),
|
||||
});
|
||||
|
||||
function updateBlockIDs(graph: Graph) {
|
||||
// https://github.com/Significant-Gravitas/AutoGPT/issues/8223
|
||||
const updatedBlockIDMap: Record<string, string> = {
|
||||
"a1b2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6":
|
||||
"436c3984-57fd-4b85-8e9a-459b356883bd",
|
||||
"b2g2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6":
|
||||
"0e50422c-6dee-4145-83d6-3a5a392f65de",
|
||||
"c3d4e5f6-7g8h-9i0j-1k2l-m3n4o5p6q7r8":
|
||||
"a0a69be1-4528-491c-a85a-a4ab6873e3f0",
|
||||
"c3d4e5f6-g7h8-i9j0-k1l2-m3n4o5p6q7r8":
|
||||
"32a87eab-381e-4dd4-bdb8-4c47151be35a",
|
||||
"b2c3d4e5-6f7g-8h9i-0j1k-l2m3n4o5p6q7":
|
||||
"87840993-2053-44b7-8da4-187ad4ee518c",
|
||||
"h1i2j3k4-5l6m-7n8o-9p0q-r1s2t3u4v5w6":
|
||||
"d0822ab5-9f8a-44a3-8971-531dd0178b6b",
|
||||
"d3f4g5h6-1i2j-3k4l-5m6n-7o8p9q0r1s2t":
|
||||
"df06086a-d5ac-4abb-9996-2ad0acb2eff7",
|
||||
"h5e7f8g9-1b2c-3d4e-5f6g-7h8i9j0k1l2m":
|
||||
"f5b0f5d0-1862-4d61-94be-3ad0fa772760",
|
||||
"a1234567-89ab-cdef-0123-456789abcdef":
|
||||
"4335878a-394e-4e67-adf2-919877ff49ae",
|
||||
"f8e7d6c5-b4a3-2c1d-0e9f-8g7h6i5j4k3l":
|
||||
"f66a3543-28d3-4ab5-8945-9b336371e2ce",
|
||||
"b29c1b50-5d0e-4d9f-8f9d-1b0e6fcbf0h2":
|
||||
"716a67b3-6760-42e7-86dc-18645c6e00fc",
|
||||
"31d1064e-7446-4693-o7d4-65e5ca9110d1":
|
||||
"cc10ff7b-7753-4ff2-9af6-9399b1a7eddc",
|
||||
"c6731acb-4105-4zp1-bc9b-03d0036h370g":
|
||||
"5ebe6768-8e5d-41e3-9134-1c7bd89a8d52",
|
||||
};
|
||||
graph.nodes
|
||||
.filter((node) => node.block_id in updatedBlockIDMap)
|
||||
.forEach((node) => {
|
||||
node.block_id = updatedBlockIDMap[node.block_id];
|
||||
});
|
||||
return graph;
|
||||
}
|
||||
|
||||
export const AgentImportForm: React.FC<
|
||||
React.FormHTMLAttributes<HTMLFormElement>
|
||||
> = ({ className, ...props }) => {
|
||||
@@ -116,6 +154,7 @@ export const AgentImportForm: React.FC<
|
||||
);
|
||||
}
|
||||
const agent = obj as Graph;
|
||||
updateBlockIDs(agent);
|
||||
setAgentObject(agent);
|
||||
form.setValue("agentName", agent.name);
|
||||
form.setValue("agentDescription", agent.description);
|
||||
|
||||
@@ -1,81 +1,44 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import {
|
||||
ArrowLeft,
|
||||
Download,
|
||||
Calendar,
|
||||
Tag,
|
||||
ChevronDown,
|
||||
ChevronUp,
|
||||
} from "lucide-react";
|
||||
import { ArrowLeft, Download, Calendar, Tag } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
AgentDetailResponse,
|
||||
InstallationLocation,
|
||||
} from "@/lib/marketplace-api";
|
||||
import dynamic from "next/dynamic";
|
||||
import { Node, Edge } from "@xyflow/react";
|
||||
import MarketplaceAPI from "@/lib/marketplace-api";
|
||||
import AutoGPTServerAPI, { GraphCreatable } from "@/lib/autogpt-server-api";
|
||||
|
||||
const ReactFlow = dynamic(
|
||||
() => import("@xyflow/react").then((mod) => mod.ReactFlow),
|
||||
{ ssr: false },
|
||||
);
|
||||
const Controls = dynamic(
|
||||
() => import("@xyflow/react").then((mod) => mod.Controls),
|
||||
{ ssr: false },
|
||||
);
|
||||
const Background = dynamic(
|
||||
() => import("@xyflow/react").then((mod) => mod.Background),
|
||||
{ ssr: false },
|
||||
);
|
||||
|
||||
import "@xyflow/react/dist/style.css";
|
||||
import { beautifyString } from "@/lib/utils";
|
||||
import { makeAnalyticsEvent } from "./actions";
|
||||
|
||||
function convertGraphToReactFlow(graph: any): { nodes: Node[]; edges: Edge[] } {
|
||||
const nodes: Node[] = graph.nodes.map((node: any) => {
|
||||
let label = node.block_id || "Unknown";
|
||||
try {
|
||||
label = beautifyString(label);
|
||||
} catch (error) {
|
||||
console.error("Error beautifying node label:", error);
|
||||
}
|
||||
async function downloadAgent(id: string): Promise<void> {
|
||||
const api = new MarketplaceAPI();
|
||||
try {
|
||||
const file = await api.downloadAgentFile(id);
|
||||
console.debug(`Agent file downloaded:`, file);
|
||||
|
||||
return {
|
||||
id: node.id,
|
||||
position: node.metadata.position || { x: 0, y: 0 },
|
||||
data: {
|
||||
label,
|
||||
blockId: node.block_id,
|
||||
inputDefault: node.input_default || {},
|
||||
...node, // Include all other node data
|
||||
},
|
||||
type: "custom",
|
||||
};
|
||||
});
|
||||
// Create a Blob from the file content
|
||||
const blob = new Blob([file], { type: "application/json" });
|
||||
|
||||
const edges: Edge[] = graph.links.map((link: any) => ({
|
||||
id: `${link.source_id}-${link.sink_id}`,
|
||||
source: link.source_id,
|
||||
target: link.sink_id,
|
||||
sourceHandle: link.source_name,
|
||||
targetHandle: link.sink_name,
|
||||
type: "custom",
|
||||
data: {
|
||||
sourceId: link.source_id,
|
||||
targetId: link.sink_id,
|
||||
sourceName: link.source_name,
|
||||
targetName: link.sink_name,
|
||||
isStatic: link.is_static,
|
||||
},
|
||||
}));
|
||||
// Create a temporary URL for the Blob
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
|
||||
return { nodes, edges };
|
||||
// Create a temporary anchor element
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = `agent_${id}.json`; // Set the filename
|
||||
|
||||
// Append the anchor to the body, click it, and remove it
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
|
||||
// Revoke the temporary URL
|
||||
window.URL.revokeObjectURL(url);
|
||||
} catch (error) {
|
||||
console.error(`Error downloading agent:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function installGraph(id: string): Promise<void> {
|
||||
@@ -84,12 +47,12 @@ async function installGraph(id: string): Promise<void> {
|
||||
"http://localhost:8015/api/v1/market";
|
||||
const api = new MarketplaceAPI(apiUrl);
|
||||
|
||||
const serverAPIUrl = process.env.AGPT_SERVER_API_URL;
|
||||
const serverAPIUrl = process.env.NEXT_PUBLIC_AGPT_SERVER_API_URL;
|
||||
const serverAPI = new AutoGPTServerAPI(serverAPIUrl);
|
||||
try {
|
||||
console.log(`Installing agent with id: ${id}`);
|
||||
console.debug(`Installing agent with id: ${id}`);
|
||||
let agent = await api.downloadAgent(id);
|
||||
console.log(`Agent downloaded:`, agent);
|
||||
console.debug(`Agent downloaded:`, agent);
|
||||
const data: GraphCreatable = {
|
||||
id: agent.id,
|
||||
version: agent.version,
|
||||
@@ -109,7 +72,7 @@ async function installGraph(id: string): Promise<void> {
|
||||
installation_location: InstallationLocation.CLOUD,
|
||||
},
|
||||
});
|
||||
console.log(`Agent installed successfully`, result);
|
||||
console.debug(`Agent installed successfully`, result);
|
||||
} catch (error) {
|
||||
console.error(`Error installing agent:`, error);
|
||||
throw error;
|
||||
@@ -117,9 +80,6 @@ async function installGraph(id: string): Promise<void> {
|
||||
}
|
||||
|
||||
function AgentDetailContent({ agent }: { agent: AgentDetailResponse }) {
|
||||
const [isGraphExpanded, setIsGraphExpanded] = useState(false);
|
||||
const { nodes, edges } = convertGraphToReactFlow(agent.graph);
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-7xl px-4 py-4 sm:px-6 lg:px-8">
|
||||
<div className="mb-4 flex items-center justify-between">
|
||||
@@ -130,13 +90,22 @@ function AgentDetailContent({ agent }: { agent: AgentDetailResponse }) {
|
||||
<ArrowLeft className="mr-2" size={20} />
|
||||
Back to Marketplace
|
||||
</Link>
|
||||
<Button
|
||||
onClick={() => installGraph(agent.id)}
|
||||
className="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
|
||||
>
|
||||
<Download className="mr-2" size={16} />
|
||||
Download Agent
|
||||
</Button>
|
||||
<div className="flex space-x-4">
|
||||
<Button
|
||||
onClick={() => installGraph(agent.id)}
|
||||
className="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
|
||||
>
|
||||
<Download className="mr-2" size={16} />
|
||||
Save to Templates
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => downloadAgent(agent.id)}
|
||||
className="inline-flex items-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
|
||||
>
|
||||
<Download className="mr-2" size={16} />
|
||||
Download Agent
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="overflow-hidden bg-white shadow sm:rounded-lg">
|
||||
<div className="px-4 py-5 sm:px-6">
|
||||
|
||||
27
autogpt_platform/frontend/src/components/nav/MarketPopup.tsx
Normal file
27
autogpt_platform/frontend/src/components/nav/MarketPopup.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import { ButtonHTMLAttributes } from "react";
|
||||
import React from "react";
|
||||
|
||||
interface MarketPopupProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
marketplaceUrl?: string;
|
||||
}
|
||||
|
||||
export default function MarketPopup({
|
||||
className = "",
|
||||
marketplaceUrl = "http://platform.agpt.co/marketplace",
|
||||
children,
|
||||
...props
|
||||
}: MarketPopupProps) {
|
||||
const openMarketplacePopup = () => {
|
||||
window.open(
|
||||
marketplaceUrl,
|
||||
"popupWindow",
|
||||
"width=600,height=400,toolbar=no,menubar=no,scrollbars=no",
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<button onClick={openMarketplacePopup} className={className} {...props}>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import Link from "next/link";
|
||||
import { BsBoxes } from "react-icons/bs";
|
||||
import { LuLaptop, LuShoppingCart } from "react-icons/lu";
|
||||
import { BehaveAs, cn } from "@/lib/utils";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { getBehaveAs } from "@/lib/utils";
|
||||
import MarketPopup from "./MarketPopup";
|
||||
|
||||
export function NavBarButtons({ className }: { className?: string }) {
|
||||
const pathname = usePathname();
|
||||
const buttons = [
|
||||
{
|
||||
href: "/",
|
||||
text: "Monitor",
|
||||
icon: <LuLaptop />,
|
||||
},
|
||||
{
|
||||
href: "/build",
|
||||
text: "Build",
|
||||
icon: <BsBoxes />,
|
||||
},
|
||||
];
|
||||
|
||||
const isCloud = getBehaveAs() === BehaveAs.CLOUD;
|
||||
|
||||
return (
|
||||
<>
|
||||
{buttons.map((button) => {
|
||||
const isActive = button.href === pathname;
|
||||
return (
|
||||
<Link
|
||||
key={button.href}
|
||||
href={button.href}
|
||||
className={cn(
|
||||
className,
|
||||
"flex items-center gap-2 rounded-xl p-3",
|
||||
isActive
|
||||
? "bg-gray-950 text-white"
|
||||
: "text-muted-foreground hover:text-foreground",
|
||||
)}
|
||||
>
|
||||
{button.icon} {button.text}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
{isCloud ? (
|
||||
<Link
|
||||
href="/marketplace"
|
||||
className={cn(
|
||||
className,
|
||||
"flex items-center gap-2 rounded-xl p-3",
|
||||
pathname === "/marketplace"
|
||||
? "bg-gray-950 text-white"
|
||||
: "text-muted-foreground hover:text-foreground",
|
||||
)}
|
||||
>
|
||||
<LuShoppingCart /> Marketplace
|
||||
</Link>
|
||||
) : (
|
||||
<MarketPopup
|
||||
className={cn(
|
||||
className,
|
||||
"flex items-center gap-2 rounded-xl p-3 text-muted-foreground hover:text-foreground",
|
||||
)}
|
||||
>
|
||||
<LuShoppingCart /> Marketplace
|
||||
</MarketPopup>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -201,3 +201,14 @@ export function filterBlocksByType<T>(
|
||||
): T[] {
|
||||
return blocks.filter(predicate);
|
||||
}
|
||||
|
||||
export enum BehaveAs {
|
||||
CLOUD = "CLOUD",
|
||||
LOCAL = "LOCAL",
|
||||
}
|
||||
|
||||
export function getBehaveAs(): BehaveAs {
|
||||
return process.env.NEXT_PUBLIC_BEHAVE_AS === "CLOUD"
|
||||
? BehaveAs.CLOUD
|
||||
: BehaveAs.LOCAL;
|
||||
}
|
||||
|
||||
@@ -740,13 +740,13 @@
|
||||
integrity sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==
|
||||
|
||||
"@radix-ui/react-context-menu@^2.2.1":
|
||||
version "2.2.1"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-context-menu/-/react-context-menu-2.2.1.tgz"
|
||||
integrity sha512-wvMKKIeb3eOrkJ96s722vcidZ+2ZNfcYZWBPRHIB1VWrF+fiF851Io6LX0kmK5wTDQFKdulCCKJk2c3SBaQHvA==
|
||||
version "2.2.2"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-context-menu/-/react-context-menu-2.2.2.tgz"
|
||||
integrity sha512-99EatSTpW+hRYHt7m8wdDlLtkmTovEe8Z/hnxUPV+SKuuNL5HWNhQI4QSdjZqNSgXHay2z4M3Dym73j9p2Gx5Q==
|
||||
dependencies:
|
||||
"@radix-ui/primitive" "1.1.0"
|
||||
"@radix-ui/react-context" "1.1.0"
|
||||
"@radix-ui/react-menu" "2.1.1"
|
||||
"@radix-ui/react-context" "1.1.1"
|
||||
"@radix-ui/react-menu" "2.1.2"
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-use-callback-ref" "1.1.0"
|
||||
"@radix-ui/react-use-controllable-state" "1.1.0"
|
||||
@@ -763,6 +763,11 @@
|
||||
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-context@1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz"
|
||||
integrity sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==
|
||||
|
||||
"@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"
|
||||
@@ -832,6 +837,17 @@
|
||||
"@radix-ui/react-use-callback-ref" "1.1.0"
|
||||
"@radix-ui/react-use-escape-keydown" "1.1.0"
|
||||
|
||||
"@radix-ui/react-dismissable-layer@1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz"
|
||||
integrity sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==
|
||||
dependencies:
|
||||
"@radix-ui/primitive" "1.1.0"
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-use-callback-ref" "1.1.0"
|
||||
"@radix-ui/react-use-escape-keydown" "1.1.0"
|
||||
|
||||
"@radix-ui/react-dropdown-menu@^2.1.1":
|
||||
version "2.1.1"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.1.tgz"
|
||||
@@ -857,6 +873,11 @@
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.0.tgz"
|
||||
integrity sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw==
|
||||
|
||||
"@radix-ui/react-focus-guards@1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz"
|
||||
integrity sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==
|
||||
|
||||
"@radix-ui/react-focus-scope@1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz"
|
||||
@@ -927,6 +948,30 @@
|
||||
aria-hidden "^1.1.1"
|
||||
react-remove-scroll "2.5.7"
|
||||
|
||||
"@radix-ui/react-menu@2.1.2":
|
||||
version "2.1.2"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.2.tgz"
|
||||
integrity sha512-lZ0R4qR2Al6fZ4yCCZzu/ReTFrylHFxIqy7OezIpWF4bL0o9biKo0pFIvkaew3TyZ9Fy5gYVrR5zCGZBVbO1zg==
|
||||
dependencies:
|
||||
"@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.1"
|
||||
"@radix-ui/react-direction" "1.1.0"
|
||||
"@radix-ui/react-dismissable-layer" "1.1.1"
|
||||
"@radix-ui/react-focus-guards" "1.1.1"
|
||||
"@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.2"
|
||||
"@radix-ui/react-presence" "1.1.1"
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-roving-focus" "1.1.0"
|
||||
"@radix-ui/react-slot" "1.1.0"
|
||||
"@radix-ui/react-use-callback-ref" "1.1.0"
|
||||
aria-hidden "^1.1.1"
|
||||
react-remove-scroll "2.6.0"
|
||||
|
||||
"@radix-ui/react-popover@^1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.1.tgz"
|
||||
@@ -980,6 +1025,14 @@
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-use-layout-effect" "1.1.0"
|
||||
|
||||
"@radix-ui/react-portal@1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.2.tgz"
|
||||
integrity sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg==
|
||||
dependencies:
|
||||
"@radix-ui/react-primitive" "2.0.0"
|
||||
"@radix-ui/react-use-layout-effect" "1.1.0"
|
||||
|
||||
"@radix-ui/react-presence@1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz"
|
||||
@@ -997,6 +1050,14 @@
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
"@radix-ui/react-use-layout-effect" "1.1.0"
|
||||
|
||||
"@radix-ui/react-presence@1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz"
|
||||
integrity sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==
|
||||
dependencies:
|
||||
"@radix-ui/react-compose-refs" "1.1.0"
|
||||
"@radix-ui/react-use-layout-effect" "1.1.0"
|
||||
|
||||
"@radix-ui/react-primitive@1.0.3":
|
||||
version "1.0.3"
|
||||
resolved "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz"
|
||||
@@ -1701,10 +1762,10 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/node@*", "@types/node@^20":
|
||||
version "20.16.1"
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-20.16.1.tgz"
|
||||
integrity sha512-zJDo7wEadFtSyNz5QITDfRcrhqDvQI1xQNQ0VoizPjM/dVAODqqIUWbJPkvsxmTI0MYRGRikcdjMPhOssnPejQ==
|
||||
"@types/node@*", "@types/node@^22.7.3":
|
||||
version "22.7.4"
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz"
|
||||
integrity sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==
|
||||
dependencies:
|
||||
undici-types "~6.19.2"
|
||||
|
||||
@@ -4998,7 +5059,7 @@ react-modal@^3.16.1:
|
||||
react-lifecycles-compat "^3.0.0"
|
||||
warning "^4.0.3"
|
||||
|
||||
react-remove-scroll-bar@^2.3.3, react-remove-scroll-bar@^2.3.4:
|
||||
react-remove-scroll-bar@^2.3.3, react-remove-scroll-bar@^2.3.4, react-remove-scroll-bar@^2.3.6:
|
||||
version "2.3.6"
|
||||
resolved "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz"
|
||||
integrity sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==
|
||||
@@ -5028,6 +5089,17 @@ react-remove-scroll@2.5.7:
|
||||
use-callback-ref "^1.3.0"
|
||||
use-sidecar "^1.1.2"
|
||||
|
||||
react-remove-scroll@2.6.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz"
|
||||
integrity sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ==
|
||||
dependencies:
|
||||
react-remove-scroll-bar "^2.3.6"
|
||||
react-style-singleton "^2.2.1"
|
||||
tslib "^2.1.0"
|
||||
use-callback-ref "^1.3.0"
|
||||
use-sidecar "^1.1.2"
|
||||
|
||||
react-shepherd@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.npmjs.org/react-shepherd/-/react-shepherd-6.1.1.tgz"
|
||||
|
||||
@@ -61,4 +61,5 @@ env:
|
||||
GOOGLE_CLIENT_ID: ""
|
||||
GOOGLE_CLIENT_SECRET: ""
|
||||
NEXT_PUBLIC_SUPABASE_URL: ""
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY: ""
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY: ""
|
||||
NEXT_PUBLIC_BEHAVE_AS: "CLOUD"
|
||||
@@ -0,0 +1,26 @@
|
||||
apiVersion: cloud.google.com/v1
|
||||
kind: BackendConfig
|
||||
metadata:
|
||||
name: {{ include "autogpt-server.fullname" . }}-backend-config
|
||||
spec:
|
||||
customRequestHeaders:
|
||||
headers:
|
||||
- "Access-Control-Allow-Origin:{{ .Values.cors.allowOrigin }}"
|
||||
- "Access-Control-Allow-Methods:{{ .Values.cors.allowMethods | join "," }}"
|
||||
- "Access-Control-Allow-Headers:{{ .Values.cors.allowHeaders | join "," }}"
|
||||
- "Access-Control-Max-Age:{{ .Values.cors.maxAge }}"
|
||||
{{- if .Values.cors.allowCredentials }}
|
||||
- "Access-Control-Allow-Credentials:true"
|
||||
{{- end }}
|
||||
customResponseHeaders:
|
||||
headers:
|
||||
- "Access-Control-Allow-Origin:{{ .Values.cors.allowOrigin }}"
|
||||
- "Access-Control-Allow-Methods:{{ .Values.cors.allowMethods | join "," }}"
|
||||
- "Access-Control-Allow-Headers:{{ .Values.cors.allowHeaders | join "," }}"
|
||||
- "Access-Control-Max-Age:{{ .Values.cors.maxAge }}"
|
||||
{{- if .Values.cors.allowCredentials }}
|
||||
- "Access-Control-Allow-Credentials:true"
|
||||
{{- end }}
|
||||
timeoutSec: 1800
|
||||
connectionDraining:
|
||||
drainingTimeoutSec: 1800
|
||||
@@ -0,0 +1,68 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "autogpt-server.fullname" . }}-executor
|
||||
labels:
|
||||
app.kubernetes.io/component: executor
|
||||
spec:
|
||||
{{- if not .Values.autoscaling.enabled }}
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
{{- end }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/component: executor
|
||||
template:
|
||||
metadata:
|
||||
{{- with .Values.podAnnotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
app.kubernetes.io/component: executor
|
||||
{{- with .Values.podLabels }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- with .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "autogpt-server.serviceAccountName" . }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: {{ include "autogpt-server.fullname" . }}-config
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
command: ["poetry", "run", "executor"]
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {{ .Values.serviceExecutor.port }}
|
||||
protocol: TCP
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
{{- with .Values.volumeMounts }}
|
||||
volumeMounts:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.volumes }}
|
||||
volumes:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
@@ -44,6 +44,9 @@ spec:
|
||||
- name: http
|
||||
containerPort: {{ .Values.service.port }}
|
||||
protocol: TCP
|
||||
- name: pyro
|
||||
containerPort: 8004
|
||||
protocol: TCP
|
||||
livenessProbe:
|
||||
{{- toYaml .Values.livenessProbe | nindent 12 }}
|
||||
readinessProbe:
|
||||
@@ -54,15 +57,6 @@ spec:
|
||||
volumeMounts:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
- name: cloud-sql-proxy
|
||||
image: "{{ .Values.cloudSqlProxy.image.repository }}:{{ .Values.cloudSqlProxy.image.tag }}"
|
||||
args:
|
||||
- "--structured-logs"
|
||||
{{- if .Values.cloudSqlProxy.usePrivateIp }}
|
||||
- "--private-ip"
|
||||
{{- end }}
|
||||
- "--port={{ .Values.cloudSqlProxy.port }}"
|
||||
- "{{ .Values.cloudSqlProxy.instanceConnectionName }}"
|
||||
{{- with .Values.volumes }}
|
||||
volumes:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "autogpt-server.fullname" . }}-executor
|
||||
labels:
|
||||
app.kubernetes.io/component: executor
|
||||
{{- with .Values.service.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
type: {{ .Values.serviceExecutor.type }}
|
||||
ports:
|
||||
- port: {{ .Values.serviceExecutor.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
selector:
|
||||
app.kubernetes.io/component: executor
|
||||
@@ -15,5 +15,11 @@ spec:
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
{{- if .Values.service.pyroDaemonPort }}
|
||||
- port: {{ .Values.service.pyroDaemonPort }}
|
||||
targetPort: pyro
|
||||
protocol: TCP
|
||||
name: pyro
|
||||
{{- end }}
|
||||
selector:
|
||||
{{- include "autogpt-server.selectorLabels" . | nindent 4 }}
|
||||
{{- include "autogpt-server.selectorLabels" . | nindent 4 }}
|
||||
@@ -12,10 +12,18 @@ serviceAccount:
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 8000
|
||||
targetPort: 8000
|
||||
port: 8006
|
||||
pyroDaemonPort: 8004
|
||||
annotations:
|
||||
cloud.google.com/neg: '{"ingress": true}'
|
||||
beta.cloud.google.com/backend-config: '{"default": "autogpt-server-backend-config"}'
|
||||
|
||||
serviceExecutor:
|
||||
type: ClusterIP
|
||||
port: 8002
|
||||
targetPort: 8002
|
||||
annotations:
|
||||
beta.cloud.google.com/backend-config: '{"default": "autogpt-server-backend-config"}'
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
@@ -33,12 +41,12 @@ ingress:
|
||||
backend:
|
||||
service:
|
||||
name: autogpt-server
|
||||
port: 8000
|
||||
port: 8006
|
||||
defaultBackend:
|
||||
service:
|
||||
name: autogpt-server
|
||||
port:
|
||||
number: 8000
|
||||
number: 8006
|
||||
|
||||
resources:
|
||||
requests:
|
||||
@@ -46,12 +54,12 @@ resources:
|
||||
memory: 256Mi
|
||||
limits:
|
||||
cpu: 2
|
||||
memory: 2Gi
|
||||
memory: 10Gi
|
||||
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /docs
|
||||
port: 8000
|
||||
port: 8006
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
@@ -59,7 +67,7 @@ livenessProbe:
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /docs
|
||||
port: 8000
|
||||
port: 8006
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
@@ -67,28 +75,39 @@ readinessProbe:
|
||||
|
||||
domain: "dev-server.agpt.co"
|
||||
|
||||
cloudSqlProxy:
|
||||
image:
|
||||
repository: gcr.io/cloud-sql-connectors/cloud-sql-proxy
|
||||
tag: 2.11.4
|
||||
instanceConnectionName: "agpt-dev:us-central1:agpt-server-dev"
|
||||
port: 5432
|
||||
resources:
|
||||
requests:
|
||||
memory: "2Gi"
|
||||
cpu: "1"
|
||||
cors:
|
||||
allowOrigin: "https://dev-builder.agpt.co"
|
||||
allowMethods:
|
||||
- "GET"
|
||||
- "POST"
|
||||
- "PUT"
|
||||
- "DELETE"
|
||||
- "OPTIONS"
|
||||
allowHeaders:
|
||||
- "Content-Type"
|
||||
- "Authorization"
|
||||
maxAge: 3600
|
||||
allowCredentials: true
|
||||
|
||||
env:
|
||||
APP_ENV: "dev"
|
||||
PYRO_HOST: "0.0.0.0"
|
||||
NUM_GRAPH_WORKERS: 100
|
||||
NUM_NODE_WORKERS: 5
|
||||
ENABLE_AUTH: "true"
|
||||
REDIS_HOST: "redis-dev-master.redis-dev.svc.cluster.local"
|
||||
REDIS_PORT: "6379"
|
||||
OPENAI_API_KEY: ""
|
||||
SUPABASE_JWT_SECRET: ""
|
||||
REDIS_PASSWORD: "password"
|
||||
NUM_GRAPH_WORKERS: 10
|
||||
NUM_NODE_WORKERS: 5
|
||||
DATABASE_URL: ""
|
||||
SENTRY_DSN: ""
|
||||
ENABLE_CREDIT: "true"
|
||||
BACKEND_CORS_ALLOW_ORIGINS: '["https://dev-builder.agpt.co"]'
|
||||
SUPABASE_SERVICE_ROLE_KEY: ""
|
||||
GITHUB_CLIENT_ID: ""
|
||||
GITHUB_CLIENT_SECRET: ""
|
||||
FRONTEND_BASE_URL: ""
|
||||
SUPABASE_URL: ""
|
||||
SUPABASE_JWT_SECRET: ""
|
||||
FRONTEND_BASE_URL: "https://dev-builder.agpt.co/"
|
||||
SUPABASE_URL: "https://adfjtextkuilwuhzdjpf.supabase.co"
|
||||
AGENTSERVER_HOST: "autogpt-server.dev-agpt.svc.cluster.local"
|
||||
EXECUTIONMANAGER_HOST: "autogpt-server-executor.dev-agpt.svc.cluster.local"
|
||||
113
autogpt_platform/infra/helm/autogpt-server/values.prod.yaml
Normal file
113
autogpt_platform/infra/helm/autogpt-server/values.prod.yaml
Normal file
@@ -0,0 +1,113 @@
|
||||
# prod values, overwrite base values as needed.
|
||||
|
||||
image:
|
||||
repository: us-east1-docker.pkg.dev/agpt-prod/agpt-backend-prod/agpt-backend-prod
|
||||
pullPolicy: Always
|
||||
tag: "latest"
|
||||
|
||||
serviceAccount:
|
||||
annotations:
|
||||
iam.gke.io/gcp-service-account: "prod-agpt-server-sa@agpt-prod.iam.gserviceaccount.com"
|
||||
name: "prod-agpt-server-sa"
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 8006
|
||||
pyroDaemonPort: 8004
|
||||
annotations:
|
||||
cloud.google.com/neg: '{"ingress": true}'
|
||||
beta.cloud.google.com/backend-config: '{"default": "autogpt-server-backend-config"}'
|
||||
|
||||
serviceExecutor:
|
||||
type: ClusterIP
|
||||
port: 8002
|
||||
targetPort: 8002
|
||||
annotations:
|
||||
beta.cloud.google.com/backend-config: '{"default": "autogpt-server-backend-config"}'
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
className: "gce"
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: gce
|
||||
kubernetes.io/ingress.global-static-ip-name: "agpt-prod-agpt-backend-ip"
|
||||
networking.gke.io/managed-certificates: "autogpt-server-cert"
|
||||
networking.gke.io/v1beta1.FrontendConfig: "autogpt-server-frontend-config"
|
||||
hosts:
|
||||
- host: backend.agpt.co
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: autogpt-server
|
||||
port: 8006
|
||||
defaultBackend:
|
||||
service:
|
||||
name: autogpt-server
|
||||
port:
|
||||
number: 8006
|
||||
|
||||
resources:
|
||||
requests:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
limits:
|
||||
cpu: 2
|
||||
memory: 10Gi
|
||||
|
||||
cors:
|
||||
allowOrigin: "https://platform.agpt.co"
|
||||
allowMethods:
|
||||
- "GET"
|
||||
- "POST"
|
||||
- "PUT"
|
||||
- "DELETE"
|
||||
- "OPTIONS"
|
||||
allowHeaders:
|
||||
- "Content-Type"
|
||||
- "Authorization"
|
||||
maxAge: 3600
|
||||
allowCredentials: true
|
||||
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /docs
|
||||
port: 8006
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 6
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /docs
|
||||
port: 8006
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 6
|
||||
|
||||
domain: "backend.agpt.co"
|
||||
|
||||
env:
|
||||
APP_ENV: "prod"
|
||||
PYRO_HOST: "0.0.0.0"
|
||||
ENABLE_AUTH: "true"
|
||||
REDIS_HOST: "redis-prod-master.redis-prod.svc.cluster.local"
|
||||
REDIS_PORT: "6379"
|
||||
OPENAI_API_KEY: ""
|
||||
REDIS_PASSWORD: ""
|
||||
NUM_GRAPH_WORKERS: 10
|
||||
NUM_NODE_WORKERS: 5
|
||||
ENABLE_CREDIT: "true"
|
||||
BACKEND_CORS_ALLOW_ORIGINS: '["https://platform.agpt.co"]'
|
||||
SUPABASE_JWT_SECRET: ""
|
||||
DATABASE_URL: ""
|
||||
SENTRY_DSN: ""
|
||||
SUPABASE_SERVICE_ROLE_KEY: ""
|
||||
FRONTEND_BASE_URL: "https://platform.agpt.co/"
|
||||
SUPABASE_URL: "https://bgwpwdsxblryihinutbx.supabase.co"
|
||||
AGENTSERVER_HOST: "autogpt-server.prod-agpt.svc.cluster.local"
|
||||
EXECUTIONMANAGER_HOST: "autogpt-server-executor.prod-agpt.svc.cluster.local"
|
||||
GITHUB_CLIENT_ID: ""
|
||||
GITHUB_CLIENT_SECRET: ""
|
||||
@@ -45,17 +45,9 @@ resources:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
cpu: 500m
|
||||
memory: 512Mi
|
||||
cpu: 1
|
||||
memory: 1Gi
|
||||
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
|
||||
autoscaling:
|
||||
enabled: false
|
||||
@@ -75,6 +67,21 @@ affinity: {}
|
||||
|
||||
domain: ""
|
||||
|
||||
cors:
|
||||
allowOrigins:
|
||||
- "https://dev-builder.agpt.co"
|
||||
allowMethods:
|
||||
- "GET"
|
||||
- "POST"
|
||||
- "PUT"
|
||||
- "DELETE"
|
||||
- "OPTIONS"
|
||||
allowHeaders:
|
||||
- "Content-Type"
|
||||
- "Authorization"
|
||||
maxAge: 3600
|
||||
allowCredentials: true
|
||||
|
||||
cloudSqlProxy:
|
||||
image:
|
||||
repository: gcr.io/cloud-sql-connectors/cloud-sql-proxy
|
||||
|
||||
@@ -6,4 +6,5 @@ DATABASE_URL="postgresql://${DB_USER}:${DB_PASS}@localhost:${DB_PORT}/${DB_NAME}
|
||||
SENTRY_DSN=https://11d0640fef35640e0eb9f022eb7d7626@o4505260022104064.ingest.us.sentry.io/4507890252447744
|
||||
|
||||
ENABLE_AUTH=true
|
||||
SUPABASE_JWT_SECRET=our-super-secret-jwt-token-with-at-least-32-characters-long
|
||||
SUPABASE_JWT_SECRET=our-super-secret-jwt-token-with-at-least-32-characters-long
|
||||
BACKEND_CORS_ALLOW_ORIGINS="http://localhost:3000,http://127.0.0.1:3000"
|
||||
@@ -593,24 +593,24 @@ async def get_not_featured_agents(
|
||||
agents = await prisma.client.get_client().query_raw(
|
||||
query=f"""
|
||||
SELECT
|
||||
"Agents".id,
|
||||
"Agents"."createdAt",
|
||||
"Agents"."updatedAt",
|
||||
"Agents".version,
|
||||
"Agents".name,
|
||||
LEFT("Agents".description, 500) AS description,
|
||||
"Agents".author,
|
||||
"Agents".keywords,
|
||||
"Agents".categories,
|
||||
"Agents".graph,
|
||||
"Agents"."submissionStatus",
|
||||
"Agents"."submissionDate",
|
||||
"Agents".search::text AS search
|
||||
FROM "Agents"
|
||||
LEFT JOIN "FeaturedAgent" ON "Agents"."id" = "FeaturedAgent"."agentId"
|
||||
WHERE ("FeaturedAgent"."agentId" IS NULL OR "FeaturedAgent"."featuredCategories" = '{{}}')
|
||||
AND "Agents"."submissionStatus" = 'APPROVED'
|
||||
ORDER BY "Agents"."createdAt" DESC
|
||||
"market"."Agents".id,
|
||||
"market"."Agents"."createdAt",
|
||||
"market"."Agents"."updatedAt",
|
||||
"market"."Agents".version,
|
||||
"market"."Agents".name,
|
||||
LEFT("market"."Agents".description, 500) AS description,
|
||||
"market"."Agents".author,
|
||||
"market"."Agents".keywords,
|
||||
"market"."Agents".categories,
|
||||
"market"."Agents".graph,
|
||||
"market"."Agents"."submissionStatus",
|
||||
"market"."Agents"."submissionDate",
|
||||
"market"."Agents".search::text AS search
|
||||
FROM "market"."Agents"
|
||||
LEFT JOIN "market"."FeaturedAgent" ON "market"."Agents"."id" = "market"."FeaturedAgent"."agentId"
|
||||
WHERE ("market"."FeaturedAgent"."agentId" IS NULL OR "market"."FeaturedAgent"."featuredCategories" = '{{}}')
|
||||
AND "market"."Agents"."submissionStatus" = 'APPROVED'
|
||||
ORDER BY "market"."Agents"."createdAt" DESC
|
||||
LIMIT {page_size} OFFSET {page_size * (page - 1)}
|
||||
""",
|
||||
model=prisma.models.Agents,
|
||||
@@ -630,24 +630,20 @@ async def get_all_categories() -> market.model.CategoriesResponse:
|
||||
CategoriesResponse: A list of unique categories.
|
||||
"""
|
||||
try:
|
||||
categories = await prisma.client.get_client().query_first(
|
||||
query="""
|
||||
SELECT ARRAY_AGG(DISTINCT category ORDER BY category) AS unique_categories
|
||||
FROM (
|
||||
SELECT UNNEST(categories) AS category
|
||||
FROM "Agents"
|
||||
) subquery;
|
||||
""",
|
||||
model=market.model.CategoriesResponse,
|
||||
)
|
||||
if not categories:
|
||||
return market.model.CategoriesResponse(unique_categories=[])
|
||||
agents = await prisma.models.Agents.prisma().find_many(distinct=["categories"])
|
||||
|
||||
return categories
|
||||
# Aggregate categories on the Python side
|
||||
all_categories = set()
|
||||
for agent in agents:
|
||||
all_categories.update(agent.categories)
|
||||
|
||||
unique_categories = sorted(list(all_categories))
|
||||
|
||||
return market.model.CategoriesResponse(unique_categories=unique_categories)
|
||||
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)}")
|
||||
# Return an empty list of categories in case of unexpected errors
|
||||
return market.model.CategoriesResponse(unique_categories=[])
|
||||
|
||||
|
||||
|
||||
@@ -49,13 +49,15 @@ Follow these steps to create and test a new block:
|
||||
|
||||
4. **Implement the `__init__` method, including test data and mocks:**
|
||||
|
||||
!!! important
|
||||
Use UUID generator (e.g. https://www.uuidgenerator.net/) for every new block `id` and *do not* make up your own. Alternatively, you can run this python code to generate an uuid: `print(__import__('uuid').uuid4())`
|
||||
|
||||
```python
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
# Unique ID for the block, used across users for templates
|
||||
# you can generate this with this python one liner
|
||||
# print(__import__('uuid').uuid4())
|
||||
id="h5e7f8g9-1b2c-3d4e-5f6g-7h8i9j0k1l2m",
|
||||
# If you are an AI leave it as is or change to "generate-proper-uuid"
|
||||
id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
|
||||
input_schema=WikipediaSummaryBlock.Input, # Assign input schema
|
||||
output_schema=WikipediaSummaryBlock.Output, # Assign output schema
|
||||
|
||||
|
||||
Reference in New Issue
Block a user