Merge branch 'dev' into swiftyos/update-block-errors

This commit is contained in:
Nicholas Tindle
2025-12-01 12:22:58 -06:00
committed by GitHub
144 changed files with 2216 additions and 621 deletions

View File

@@ -112,12 +112,6 @@ def GoogleDrivePickerField(
# Use drive.file for minimal scope - only access files selected by user in picker
picker_scopes.add("https://www.googleapis.com/auth/drive.file")
views = set(allowed_views or [])
if "SPREADSHEETS" in views:
picker_scopes.add("https://www.googleapis.com/auth/spreadsheets.readonly")
if "DOCUMENTS" in views or "DOCS" in views:
picker_scopes.add("https://www.googleapis.com/auth/documents.readonly")
picker_config["scopes"] = sorted(picker_scopes)
# Set appropriate default value

View File

@@ -250,9 +250,7 @@ class BatchOperation(BlockSchemaInput):
class GoogleSheetsReadBlock(Block):
class Input(BlockSchemaInput):
credentials: GoogleCredentialsInput = GoogleCredentialsField(
["https://www.googleapis.com/auth/spreadsheets.readonly"]
)
credentials: GoogleCredentialsInput = GoogleCredentialsField([])
spreadsheet: GoogleDriveFile = GoogleDrivePickerField(
title="Spreadsheet",
description="Select a Google Sheets spreadsheet",
@@ -375,9 +373,7 @@ class GoogleSheetsReadBlock(Block):
class GoogleSheetsWriteBlock(Block):
class Input(BlockSchemaInput):
credentials: GoogleCredentialsInput = GoogleCredentialsField(
["https://www.googleapis.com/auth/spreadsheets"]
)
credentials: GoogleCredentialsInput = GoogleCredentialsField([])
spreadsheet: GoogleDriveFile = GoogleDrivePickerField(
title="Spreadsheet",
description="Select a Google Sheets spreadsheet",
@@ -513,9 +509,7 @@ class GoogleSheetsWriteBlock(Block):
class GoogleSheetsAppendBlock(Block):
class Input(BlockSchemaInput):
credentials: GoogleCredentialsInput = GoogleCredentialsField(
["https://www.googleapis.com/auth/spreadsheets"]
)
credentials: GoogleCredentialsInput = GoogleCredentialsField([])
spreadsheet: GoogleDriveFile = GoogleDrivePickerField(
title="Spreadsheet",
description="Select a Google Sheets spreadsheet",
@@ -696,9 +690,7 @@ class GoogleSheetsAppendBlock(Block):
class GoogleSheetsClearBlock(Block):
class Input(BlockSchemaInput):
credentials: GoogleCredentialsInput = GoogleCredentialsField(
["https://www.googleapis.com/auth/spreadsheets"]
)
credentials: GoogleCredentialsInput = GoogleCredentialsField([])
spreadsheet: GoogleDriveFile = GoogleDrivePickerField(
title="Spreadsheet",
description="Select a Google Sheets spreadsheet",
@@ -806,9 +798,7 @@ class GoogleSheetsClearBlock(Block):
class GoogleSheetsMetadataBlock(Block):
class Input(BlockSchemaInput):
credentials: GoogleCredentialsInput = GoogleCredentialsField(
["https://www.googleapis.com/auth/spreadsheets.readonly"]
)
credentials: GoogleCredentialsInput = GoogleCredentialsField([])
spreadsheet: GoogleDriveFile = GoogleDrivePickerField(
title="Spreadsheet",
description="Select a Google Sheets spreadsheet",
@@ -928,9 +918,7 @@ class GoogleSheetsMetadataBlock(Block):
class GoogleSheetsManageSheetBlock(Block):
class Input(BlockSchemaInput):
credentials: GoogleCredentialsInput = GoogleCredentialsField(
["https://www.googleapis.com/auth/spreadsheets"]
)
credentials: GoogleCredentialsInput = GoogleCredentialsField([])
spreadsheet: GoogleDriveFile = GoogleDrivePickerField(
title="Spreadsheet",
description="Select a Google Sheets spreadsheet",
@@ -1085,9 +1073,7 @@ class GoogleSheetsManageSheetBlock(Block):
class GoogleSheetsBatchOperationsBlock(Block):
class Input(BlockSchemaInput):
credentials: GoogleCredentialsInput = GoogleCredentialsField(
["https://www.googleapis.com/auth/spreadsheets"]
)
credentials: GoogleCredentialsInput = GoogleCredentialsField([])
spreadsheet: GoogleDriveFile = GoogleDrivePickerField(
title="Spreadsheet",
description="Select a Google Sheets spreadsheet",
@@ -1242,9 +1228,7 @@ class GoogleSheetsBatchOperationsBlock(Block):
class GoogleSheetsFindReplaceBlock(Block):
class Input(BlockSchemaInput):
credentials: GoogleCredentialsInput = GoogleCredentialsField(
["https://www.googleapis.com/auth/spreadsheets"]
)
credentials: GoogleCredentialsInput = GoogleCredentialsField([])
spreadsheet: GoogleDriveFile = GoogleDrivePickerField(
title="Spreadsheet",
description="Select a Google Sheets spreadsheet",
@@ -1392,9 +1376,7 @@ class GoogleSheetsFindReplaceBlock(Block):
class GoogleSheetsFindBlock(Block):
class Input(BlockSchemaInput):
credentials: GoogleCredentialsInput = GoogleCredentialsField(
["https://www.googleapis.com/auth/spreadsheets.readonly"]
)
credentials: GoogleCredentialsInput = GoogleCredentialsField([])
spreadsheet: GoogleDriveFile = GoogleDrivePickerField(
title="Spreadsheet",
description="Select a Google Sheets spreadsheet",
@@ -1700,9 +1682,7 @@ class GoogleSheetsFindBlock(Block):
class GoogleSheetsFormatBlock(Block):
class Input(BlockSchemaInput):
credentials: GoogleCredentialsInput = GoogleCredentialsField(
["https://www.googleapis.com/auth/spreadsheets"]
)
credentials: GoogleCredentialsInput = GoogleCredentialsField([])
spreadsheet: GoogleDriveFile = GoogleDrivePickerField(
title="Spreadsheet",
description="Select a Google Sheets spreadsheet",
@@ -1875,9 +1855,7 @@ class GoogleSheetsFormatBlock(Block):
class GoogleSheetsCreateSpreadsheetBlock(Block):
class Input(BlockSchemaInput):
credentials: GoogleCredentialsInput = GoogleCredentialsField(
["https://www.googleapis.com/auth/spreadsheets"]
)
credentials: GoogleCredentialsInput = GoogleCredentialsField([])
title: str = SchemaField(
description="The title of the new spreadsheet",
)
@@ -2017,9 +1995,7 @@ class GoogleSheetsUpdateCellBlock(Block):
"""Update a single cell in a Google Sheets spreadsheet."""
class Input(BlockSchemaInput):
credentials: GoogleCredentialsInput = GoogleCredentialsField(
["https://www.googleapis.com/auth/spreadsheets"]
)
credentials: GoogleCredentialsInput = GoogleCredentialsField([])
spreadsheet: GoogleDriveFile = GoogleDrivePickerField(
title="Spreadsheet",
description="Select a Google Sheets spreadsheet",

View File

@@ -5,10 +5,19 @@ import pytest
from backend.data.block import Block, get_blocks
from backend.util.test import execute_block_test
SKIP_BLOCK_TESTS = {
"HumanInTheLoopBlock",
}
@pytest.mark.parametrize("block", get_blocks().values(), ids=lambda b: b().name)
async def test_available_blocks(block: Type[Block]):
await execute_block_test(block())
block_instance = block()
if block_instance.__class__.__name__ in SKIP_BLOCK_TESTS:
pytest.skip(
f"Skipping {block_instance.__class__.__name__} - requires external service"
)
await execute_block_test(block_instance)
@pytest.mark.parametrize("block", get_blocks().values(), ids=lambda b: b().name)

View File

@@ -14,6 +14,10 @@ from backend.data.human_review import (
process_all_reviews_for_execution,
)
pytestmark = pytest.mark.skip(
reason="Tests failing in CI due to mocking issues - skipping until refactored"
)
@pytest.fixture
def sample_db_review():

View File

@@ -3,6 +3,7 @@ from fastapi import FastAPI
from backend.monitoring.instrumentation import instrument_fastapi
from backend.server.middleware.security import SecurityHeadersMiddleware
from .routes.tools import tools_router
from .routes.v1 import v1_router
external_app = FastAPI(
@@ -14,6 +15,7 @@ external_app = FastAPI(
external_app.add_middleware(SecurityHeadersMiddleware)
external_app.include_router(v1_router, prefix="/v1")
external_app.include_router(tools_router, prefix="/v1")
# Add Prometheus instrumentation
instrument_fastapi(

View File

@@ -0,0 +1,239 @@
"""External API routes for chat tools - stateless HTTP endpoints.
Note: These endpoints use ephemeral sessions that are not persisted to Redis.
As a result, session-based rate limiting (max_agent_runs, max_agent_schedules)
is not enforced for external API calls. Each request creates a fresh session
with zeroed counters. Rate limiting for external API consumers should be
handled separately (e.g., via API key quotas).
"""
import logging
from typing import Any
from fastapi import APIRouter, Security
from prisma.enums import APIKeyPermission
from pydantic import BaseModel, Field
from backend.data.api_key import APIKeyInfo
from backend.server.external.middleware import require_permission
from backend.server.v2.chat.model import ChatSession
from backend.server.v2.chat.tools import (
find_agent_tool,
get_agent_details_tool,
get_required_setup_info_tool,
run_agent_tool,
setup_agent_tool,
)
from backend.server.v2.chat.tools.models import ToolResponseBase
logger = logging.getLogger(__name__)
tools_router = APIRouter(prefix="/tools", tags=["tools"])
# Note: We use Security() as a function parameter dependency (api_key: APIKeyInfo = Security(...))
# rather than in the decorator's dependencies= list. This avoids duplicate permission checks
# while still enforcing auth AND giving us access to the api_key for extracting user_id.
# Request models
class FindAgentRequest(BaseModel):
query: str = Field(..., description="Search query for finding agents")
class AgentSlugRequest(BaseModel):
username_agent_slug: str = Field(
...,
description="The marketplace agent slug (e.g., 'username/agent-name')",
)
class GetRequiredSetupInfoRequest(AgentSlugRequest):
inputs: dict[str, Any] = Field(
default_factory=dict,
description="The input dictionary you plan to provide",
)
class RunAgentRequest(AgentSlugRequest):
inputs: dict[str, Any] = Field(
default_factory=dict,
description="Dictionary of input values for the agent",
)
class SetupAgentRequest(AgentSlugRequest):
setup_type: str = Field(
default="schedule",
description="Type of setup: 'schedule' for cron, 'webhook' for triggers",
)
name: str = Field(..., description="Name for this setup/schedule")
description: str | None = Field(None, description="Description of this setup")
cron: str | None = Field(
None,
description="Cron expression (5 fields: minute hour day month weekday)",
)
timezone: str = Field(
default="UTC",
description="IANA timezone (e.g., 'America/New_York', 'UTC')",
)
inputs: dict[str, Any] = Field(
default_factory=dict,
description="Dictionary with required inputs for the agent",
)
webhook_config: dict[str, Any] | None = Field(
None,
description="Webhook configuration (required if setup_type is 'webhook')",
)
def _create_ephemeral_session(user_id: str | None) -> ChatSession:
"""Create an ephemeral session for stateless API requests.
Note: These sessions are NOT persisted to Redis, so session-based rate
limiting (max_agent_runs, max_agent_schedules) will not be enforced
across requests.
"""
return ChatSession.new(user_id)
@tools_router.post(path="/find-agent")
async def find_agent(
request: FindAgentRequest,
api_key: APIKeyInfo = Security(require_permission(APIKeyPermission.USE_TOOLS)),
) -> dict[str, Any]:
"""
Search for agents in the marketplace based on capabilities and user needs.
Args:
request: Search query for finding agents
Returns:
List of matching agents or no results response
"""
session = _create_ephemeral_session(api_key.user_id)
result = await find_agent_tool._execute(
user_id=api_key.user_id,
session=session,
query=request.query,
)
return _response_to_dict(result)
@tools_router.post(path="/get-agent-details")
async def get_agent_details(
request: AgentSlugRequest,
api_key: APIKeyInfo = Security(require_permission(APIKeyPermission.USE_TOOLS)),
) -> dict[str, Any]:
"""
Get detailed information about a specific agent including inputs,
credentials required, and execution options.
Args:
request: Agent slug in format 'username/agent-name'
Returns:
Detailed agent information
"""
session = _create_ephemeral_session(api_key.user_id)
result = await get_agent_details_tool._execute(
user_id=api_key.user_id,
session=session,
username_agent_slug=request.username_agent_slug,
)
return _response_to_dict(result)
@tools_router.post(path="/get-required-setup-info")
async def get_required_setup_info(
request: GetRequiredSetupInfoRequest,
api_key: APIKeyInfo = Security(require_permission(APIKeyPermission.USE_TOOLS)),
) -> dict[str, Any]:
"""
Check if an agent can be set up with the provided input data and credentials.
Validates that you have all required inputs before running or scheduling.
Args:
request: Agent slug and optional inputs to validate
Returns:
Setup requirements and user readiness status
"""
session = _create_ephemeral_session(api_key.user_id)
result = await get_required_setup_info_tool._execute(
user_id=api_key.user_id,
session=session,
username_agent_slug=request.username_agent_slug,
inputs=request.inputs,
)
return _response_to_dict(result)
@tools_router.post(path="/run-agent")
async def run_agent(
request: RunAgentRequest,
api_key: APIKeyInfo = Security(require_permission(APIKeyPermission.USE_TOOLS)),
) -> dict[str, Any]:
"""
Run an agent immediately (one-off manual execution).
IMPORTANT: Before calling this endpoint, first call get-agent-details
to determine what inputs are required.
Args:
request: Agent slug and input values
Returns:
Execution started response with execution_id
"""
session = _create_ephemeral_session(api_key.user_id)
result = await run_agent_tool._execute(
user_id=api_key.user_id,
session=session,
username_agent_slug=request.username_agent_slug,
inputs=request.inputs,
)
return _response_to_dict(result)
@tools_router.post(path="/setup-agent")
async def setup_agent(
request: SetupAgentRequest,
api_key: APIKeyInfo = Security(require_permission(APIKeyPermission.USE_TOOLS)),
) -> dict[str, Any]:
"""
Set up an agent with credentials and configure it for scheduled execution
or webhook triggers.
For SCHEDULED execution:
- Cron format: "minute hour day month weekday"
- Examples: "0 9 * * 1-5" (9am weekdays), "0 0 * * *" (daily at midnight)
- Timezone: Use IANA timezone names like "America/New_York", "Europe/London"
For WEBHOOK triggers:
- The agent will be triggered by external events
Args:
request: Agent slug, setup type, schedule configuration, and inputs
Returns:
Schedule or webhook created response
"""
session = _create_ephemeral_session(api_key.user_id)
result = await setup_agent_tool._execute(
user_id=api_key.user_id,
session=session,
username_agent_slug=request.username_agent_slug,
setup_type=request.setup_type,
name=request.name,
description=request.description,
cron=request.cron,
timezone=request.timezone,
inputs=request.inputs,
webhook_config=request.webhook_config,
)
return _response_to_dict(result)
def _response_to_dict(result: ToolResponseBase) -> dict[str, Any]:
"""Convert a tool response to a dictionary for JSON serialization."""
return result.model_dump()

View File

@@ -1,12 +1,15 @@
import logging
import urllib.parse
from collections import defaultdict
from typing import Annotated, Any, Optional, Sequence
from typing import Annotated, Any, Literal, Optional, Sequence
from fastapi import APIRouter, Body, HTTPException, Security
from prisma.enums import AgentExecutionStatus, APIKeyPermission
from typing_extensions import TypedDict
import backend.data.block
import backend.server.v2.store.cache as store_cache
import backend.server.v2.store.model as store_model
from backend.data import execution as execution_db
from backend.data import graph as graph_db
from backend.data.api_key import APIKeyInfo
@@ -144,3 +147,149 @@ async def get_graph_execution_results(
else None
),
)
##############################################
############### Store Endpoints ##############
##############################################
@v1_router.get(
path="/store/agents",
tags=["store"],
dependencies=[Security(require_permission(APIKeyPermission.READ_STORE))],
response_model=store_model.StoreAgentsResponse,
)
async def get_store_agents(
featured: bool = False,
creator: str | None = None,
sorted_by: Literal["rating", "runs", "name", "updated_at"] | None = None,
search_query: str | None = None,
category: str | None = None,
page: int = 1,
page_size: int = 20,
) -> store_model.StoreAgentsResponse:
"""
Get a paginated list of agents from the store with optional filtering and sorting.
Args:
featured: Filter to only show featured agents
creator: Filter agents by creator username
sorted_by: Sort agents by "runs", "rating", "name", or "updated_at"
search_query: Search agents by name, subheading and description
category: Filter agents by category
page: Page number for pagination (default 1)
page_size: Number of agents per page (default 20)
Returns:
StoreAgentsResponse: Paginated list of agents matching the filters
"""
if page < 1:
raise HTTPException(status_code=422, detail="Page must be greater than 0")
if page_size < 1:
raise HTTPException(status_code=422, detail="Page size must be greater than 0")
agents = await store_cache._get_cached_store_agents(
featured=featured,
creator=creator,
sorted_by=sorted_by,
search_query=search_query,
category=category,
page=page,
page_size=page_size,
)
return agents
@v1_router.get(
path="/store/agents/{username}/{agent_name}",
tags=["store"],
dependencies=[Security(require_permission(APIKeyPermission.READ_STORE))],
response_model=store_model.StoreAgentDetails,
)
async def get_store_agent(
username: str,
agent_name: str,
) -> store_model.StoreAgentDetails:
"""
Get details of a specific store agent by username and agent name.
Args:
username: Creator's username
agent_name: Name/slug of the agent
Returns:
StoreAgentDetails: Detailed information about the agent
"""
username = urllib.parse.unquote(username).lower()
agent_name = urllib.parse.unquote(agent_name).lower()
agent = await store_cache._get_cached_agent_details(
username=username, agent_name=agent_name
)
return agent
@v1_router.get(
path="/store/creators",
tags=["store"],
dependencies=[Security(require_permission(APIKeyPermission.READ_STORE))],
response_model=store_model.CreatorsResponse,
)
async def get_store_creators(
featured: bool = False,
search_query: str | None = None,
sorted_by: Literal["agent_rating", "agent_runs", "num_agents"] | None = None,
page: int = 1,
page_size: int = 20,
) -> store_model.CreatorsResponse:
"""
Get a paginated list of store creators with optional filtering and sorting.
Args:
featured: Filter to only show featured creators
search_query: Search creators by profile description
sorted_by: Sort by "agent_rating", "agent_runs", or "num_agents"
page: Page number for pagination (default 1)
page_size: Number of creators per page (default 20)
Returns:
CreatorsResponse: Paginated list of creators matching the filters
"""
if page < 1:
raise HTTPException(status_code=422, detail="Page must be greater than 0")
if page_size < 1:
raise HTTPException(status_code=422, detail="Page size must be greater than 0")
creators = await store_cache._get_cached_store_creators(
featured=featured,
search_query=search_query,
sorted_by=sorted_by,
page=page,
page_size=page_size,
)
return creators
@v1_router.get(
path="/store/creators/{username}",
tags=["store"],
dependencies=[Security(require_permission(APIKeyPermission.READ_STORE))],
response_model=store_model.CreatorDetails,
)
async def get_store_creator(
username: str,
) -> store_model.CreatorDetails:
"""
Get details of a specific store creator by username.
Args:
username: Creator's username
Returns:
CreatorDetails: Detailed information about the creator
"""
username = urllib.parse.unquote(username).lower()
creator = await store_cache._get_cached_creator_details(username=username)
return creator

View File

@@ -64,7 +64,10 @@ async def create_session(
CreateSessionResponse: Details of the created session.
"""
logger.info(f"Creating session with user_id: {user_id}")
logger.info(
f"Creating session with user_id: "
f"...{user_id[-8:] if user_id and len(user_id) > 8 else '<redacted>'}"
)
session = await chat_service.create_chat_session(user_id)

View File

@@ -18,6 +18,10 @@ app.include_router(router, prefix="/api/review")
client = fastapi.testclient.TestClient(app)
pytestmark = pytest.mark.skip(
reason="Tests failing in CI due to mocking issues - skipping until refactored"
)
@pytest.fixture(autouse=True)
def setup_app_auth(mock_jwt_user):

View File

@@ -262,6 +262,30 @@ async def get_library_agent(id: str, user_id: str) -> library_model.LibraryAgent
if not library_agent:
raise NotFoundError(f"Library agent #{id} not found")
# Fetch marketplace listing if the agent has been published
store_listing = None
profile = None
if library_agent.AgentGraph:
store_listing = await prisma.models.StoreListing.prisma().find_first(
where={
"agentGraphId": library_agent.AgentGraph.id,
"isDeleted": False,
"hasApprovedVersion": True,
},
include={
"ActiveVersion": True,
},
)
if (
store_listing
and store_listing.ActiveVersion
and store_listing.owningUserId
):
# Fetch Profile separately since User doesn't have a direct Profile relation
profile = await prisma.models.Profile.prisma().find_first(
where={"userId": store_listing.owningUserId}
)
return library_model.LibraryAgent.from_db(
library_agent,
sub_graphs=(
@@ -269,6 +293,8 @@ async def get_library_agent(id: str, user_id: str) -> library_model.LibraryAgent
if library_agent.AgentGraph
else None
),
store_listing=store_listing,
profile=profile,
)
except prisma.errors.PrismaError as e:
@@ -396,8 +422,7 @@ async def create_library_agent(
DatabaseError: If there's an error during creation or if image generation fails.
"""
logger.info(
f"Creating library agent for graph #{graph.id} v{graph.version}; "
f"user #{user_id}"
f"Creating library agent for graph #{graph.id} v{graph.version}; user:<redacted>"
)
graph_entries = (
[graph, *graph.sub_graphs] if create_library_agents_for_sub_graphs else [graph]

View File

@@ -22,6 +22,23 @@ class LibraryAgentStatus(str, Enum):
ERROR = "ERROR" # Agent is in an error state
class MarketplaceListingCreator(pydantic.BaseModel):
"""Creator information for a marketplace listing."""
name: str
id: str
slug: str
class MarketplaceListing(pydantic.BaseModel):
"""Marketplace listing information for a library agent."""
id: str
name: str
slug: str
creator: MarketplaceListingCreator
class LibraryAgent(pydantic.BaseModel):
"""
Represents an agent in the library, including metadata for display and
@@ -39,6 +56,7 @@ class LibraryAgent(pydantic.BaseModel):
status: LibraryAgentStatus
created_at: datetime.datetime
updated_at: datetime.datetime
name: str
@@ -71,10 +89,15 @@ class LibraryAgent(pydantic.BaseModel):
# Recommended schedule cron (from marketplace agents)
recommended_schedule_cron: str | None = None
# Marketplace listing information if the agent has been published
marketplace_listing: Optional["MarketplaceListing"] = None
@staticmethod
def from_db(
agent: prisma.models.LibraryAgent,
sub_graphs: Optional[list[prisma.models.AgentGraph]] = None,
store_listing: Optional[prisma.models.StoreListing] = None,
profile: Optional[prisma.models.Profile] = None,
) -> "LibraryAgent":
"""
Factory method that constructs a LibraryAgent from a Prisma LibraryAgent
@@ -85,6 +108,8 @@ class LibraryAgent(pydantic.BaseModel):
graph = graph_model.GraphModel.from_db(agent.AgentGraph, sub_graphs=sub_graphs)
created_at = agent.createdAt
agent_updated_at = agent.AgentGraph.updatedAt
lib_agent_updated_at = agent.updatedAt
@@ -116,6 +141,21 @@ class LibraryAgent(pydantic.BaseModel):
# Hard-coded to True until a method to check is implemented
is_latest_version = True
# Build marketplace_listing if available
marketplace_listing_data = None
if store_listing and store_listing.ActiveVersion and profile:
creator_data = MarketplaceListingCreator(
name=profile.name,
id=profile.id,
slug=profile.username,
)
marketplace_listing_data = MarketplaceListing(
id=store_listing.id,
name=store_listing.ActiveVersion.name,
slug=store_listing.slug,
creator=creator_data,
)
return LibraryAgent(
id=agent.id,
graph_id=agent.agentGraphId,
@@ -124,6 +164,7 @@ class LibraryAgent(pydantic.BaseModel):
creator_name=creator_name,
creator_image_url=creator_image_url,
status=status,
created_at=created_at,
updated_at=updated_at,
name=graph.name,
description=graph.description,
@@ -140,6 +181,7 @@ class LibraryAgent(pydantic.BaseModel):
is_latest_version=is_latest_version,
is_favorite=agent.isFavorite,
recommended_schedule_cron=agent.AgentGraph.recommendedScheduleCron,
marketplace_listing=marketplace_listing_data,
)

View File

@@ -55,6 +55,7 @@ async def test_get_library_agents_success(
can_access_graph=True,
is_latest_version=True,
is_favorite=False,
created_at=datetime.datetime(2023, 1, 1, 0, 0, 0),
updated_at=datetime.datetime(2023, 1, 1, 0, 0, 0),
),
library_model.LibraryAgent(
@@ -76,6 +77,7 @@ async def test_get_library_agents_success(
can_access_graph=False,
is_latest_version=True,
is_favorite=False,
created_at=datetime.datetime(2023, 1, 1, 0, 0, 0),
updated_at=datetime.datetime(2023, 1, 1, 0, 0, 0),
),
],
@@ -149,6 +151,7 @@ async def test_get_favorite_library_agents_success(
can_access_graph=True,
is_latest_version=True,
is_favorite=True,
created_at=datetime.datetime(2023, 1, 1, 0, 0, 0),
updated_at=datetime.datetime(2023, 1, 1, 0, 0, 0),
),
],
@@ -214,6 +217,7 @@ def test_add_agent_to_library_success(
can_access_graph=True,
is_latest_version=True,
is_favorite=False,
created_at=FIXED_NOW,
updated_at=FIXED_NOW,
)

View File

@@ -28,6 +28,7 @@ from typing import (
import httpx
import uvicorn
from fastapi import FastAPI, Request, responses
from prisma.errors import DataError
from pydantic import BaseModel, TypeAdapter, create_model
import backend.util.exceptions as exceptions
@@ -193,6 +194,7 @@ EXCEPTION_MAPPING = {
e.__name__: e
for e in [
ValueError,
DataError,
RuntimeError,
TimeoutError,
ConnectionError,
@@ -411,6 +413,9 @@ class AppService(BaseAppService, ABC):
self.fastapi_app.add_exception_handler(
ValueError, self._handle_internal_http_error(400)
)
self.fastapi_app.add_exception_handler(
DataError, self._handle_internal_http_error(400)
)
self.fastapi_app.add_exception_handler(
Exception, self._handle_internal_http_error(500)
)
@@ -472,6 +477,7 @@ def get_service_client(
exclude_exceptions=(
# Don't retry these specific exceptions that won't be fixed by retrying
ValueError, # Invalid input/parameters
DataError, # Prisma data integrity errors (foreign key, unique constraints)
KeyError, # Missing required data
TypeError, # Wrong data types
AttributeError, # Missing attributes

View File

@@ -0,0 +1,2 @@
-- AlterEnum
ALTER TYPE "APIKeyPermission" ADD VALUE 'READ_STORE';

View File

@@ -0,0 +1,2 @@
-- AlterEnum
ALTER TYPE "APIKeyPermission" ADD VALUE 'USE_TOOLS';

View File

@@ -910,6 +910,8 @@ enum APIKeyPermission {
READ_GRAPH // Can get graph versions and details
EXECUTE_BLOCK // Can execute individual blocks
READ_BLOCK // Can get block information
READ_STORE // Can read store agents and creators
USE_TOOLS // Can use chat tools via external API
}
model APIKey {

View File

@@ -8,6 +8,7 @@
"creator_name": "Test Creator",
"creator_image_url": "",
"status": "COMPLETED",
"created_at": "2023-01-01T00:00:00",
"updated_at": "2023-01-01T00:00:00",
"name": "Test Agent 1",
"description": "Test Description 1",
@@ -30,7 +31,8 @@
"can_access_graph": true,
"is_latest_version": true,
"is_favorite": false,
"recommended_schedule_cron": null
"recommended_schedule_cron": null,
"marketplace_listing": null
},
{
"id": "test-agent-2",
@@ -40,6 +42,7 @@
"creator_name": "Test Creator",
"creator_image_url": "",
"status": "COMPLETED",
"created_at": "2023-01-01T00:00:00",
"updated_at": "2023-01-01T00:00:00",
"name": "Test Agent 2",
"description": "Test Description 2",
@@ -62,7 +65,8 @@
"can_access_graph": false,
"is_latest_version": true,
"is_favorite": false,
"recommended_schedule_cron": null
"recommended_schedule_cron": null,
"marketplace_listing": null
}
],
"pagination": {

View File

@@ -1,4 +1,4 @@
import { CredentialsInput } from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/CredentialsInputs/CredentialsInputs";
import { CredentialsInput } from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/modals/CredentialsInputs/CredentialsInputs";
import { CredentialsMetaInput } from "@/app/api/__generated__/models/credentialsMetaInput";
import { GraphMeta } from "@/app/api/__generated__/models/graphMeta";
import { useState } from "react";

View File

@@ -1,6 +1,6 @@
"use client";
import { RunAgentInputs } from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/RunAgentInputs/RunAgentInputs";
import { RunAgentInputs } from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/modals/RunAgentInputs/RunAgentInputs";
import {
Card,
CardContent,

View File

@@ -1,8 +1,7 @@
"use client";
import React from "react";
import { useParams } from "next/navigation";
import { RunOutputs } from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/SelectedRunView/components/RunOutputs";
import { RunOutputs } from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/selected-views/SelectedRunView/components/RunOutputs";
import { useGetV1GetSharedExecution } from "@/app/api/__generated__/endpoints/default/default";
import {
Card,
CardContent,
@@ -11,7 +10,7 @@ import {
} from "@/components/__legacy__/ui/card";
import { Alert, AlertDescription } from "@/components/molecules/Alert/Alert";
import { InfoIcon } from "lucide-react";
import { useGetV1GetSharedExecution } from "@/app/api/__generated__/endpoints/default/default";
import { useParams } from "next/navigation";
export default function SharePage() {
const params = useParams();

View File

@@ -1,4 +1,4 @@
import { OAuthPopupResultMessage } from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/CredentialsInputs/CredentialsInputs";
import { OAuthPopupResultMessage } from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/modals/CredentialsInputs/CredentialsInputs";
import { NextResponse } from "next/server";
// This route is intended to be used as the callback for integration OAuth flows,

View File

@@ -1,9 +1,13 @@
import { BlockUIType } from "@/app/(platform)/build/components/types";
import { useGraphStore } from "@/app/(platform)/build/stores/graphStore";
import { useNodeStore } from "@/app/(platform)/build/stores/nodeStore";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/atoms/Tooltip/BaseTooltip";
globalRegistry,
OutputActions,
OutputItem,
} from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/selected-views/OutputRenderers";
import { Label } from "@/components/__legacy__/ui/label";
import { ScrollArea } from "@/components/__legacy__/ui/scroll-area";
import {
Sheet,
SheetContent,
@@ -12,20 +16,16 @@ import {
SheetTitle,
SheetTrigger,
} from "@/components/__legacy__/ui/sheet";
import { BuilderActionButton } from "../BuilderActionButton";
import { BookOpenIcon } from "@phosphor-icons/react";
import { useGraphStore } from "@/app/(platform)/build/stores/graphStore";
import { useShallow } from "zustand/react/shallow";
import { useNodeStore } from "@/app/(platform)/build/stores/nodeStore";
import { BlockUIType } from "@/app/(platform)/build/components/types";
import { ScrollArea } from "@/components/__legacy__/ui/scroll-area";
import { Label } from "@/components/__legacy__/ui/label";
import { useMemo } from "react";
import {
globalRegistry,
OutputItem,
OutputActions,
} from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/OutputRenderers";
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/atoms/Tooltip/BaseTooltip";
import { BookOpenIcon } from "@phosphor-icons/react";
import { useMemo } from "react";
import { useShallow } from "zustand/react/shallow";
import { BuilderActionButton } from "../BuilderActionButton";
export const AgentOutputs = ({ flowID }: { flowID: string | null }) => {
const hasOutputs = useGraphStore(useShallow((state) => state.hasOutputs));

View File

@@ -1,10 +1,10 @@
import { CronScheduler } from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/modals/ScheduleAgentModal/components/CronScheduler/CronScheduler";
import { Button } from "@/components/atoms/Button/Button";
import { Input } from "@/components/atoms/Input/Input";
import { Text } from "@/components/atoms/Text/Text";
import { Dialog } from "@/components/molecules/Dialog/Dialog";
import { InfoIcon } from "lucide-react";
import { CronScheduler } from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/ScheduleAgentModal/components/CronScheduler/CronScheduler";
import { Text } from "@/components/atoms/Text/Text";
import { useCronSchedulerDialog } from "./useCronSchedulerDialog";
import { Input } from "@/components/atoms/Input/Input";
type CronSchedulerDialogProps = {
open: boolean;

View File

@@ -16,6 +16,7 @@ import { useCopyPaste } from "./useCopyPaste";
import { FloatingReviewsPanel } from "@/components/organisms/FloatingReviewsPanel/FloatingReviewsPanel";
import { parseAsString, useQueryStates } from "nuqs";
import { CustomControls } from "./components/CustomControl";
import { TriggerAgentBanner } from "./components/TriggerAgentBanner";
export const Flow = () => {
const [{ flowExecutionID }] = useQueryStates({
@@ -27,6 +28,9 @@ export const Flow = () => {
const onNodesChange = useNodeStore(
useShallow((state) => state.onNodesChange),
);
const hasWebhookNodes = useNodeStore(
useShallow((state) => state.hasWebhookNodes()),
);
const nodeTypes = useMemo(() => ({ custom: CustomNode }), []);
const edgeTypes = useMemo(() => ({ custom: CustomEdge }), []);
const { edges, onConnect, onEdgesChange } = useCustomEdge();
@@ -76,7 +80,7 @@ export const Flow = () => {
<Background />
<CustomControls setIsLocked={setIsLocked} isLocked={isLocked} />
<NewControlPanel />
<BuilderActions />
{hasWebhookNodes ? <TriggerAgentBanner /> : <BuilderActions />}
{<GraphLoadingBox flowContentLoading={isFlowContentLoading} />}
{isGraphRunning && <RunningBackground />}
</ReactFlow>

View File

@@ -0,0 +1,49 @@
import {
Alert,
AlertDescription,
AlertTitle,
} from "@/components/molecules/Alert/Alert";
import Link from "next/link";
import { useGetV2GetLibraryAgentByGraphId } from "@/app/api/__generated__/endpoints/library/library";
import { LibraryAgent } from "@/app/api/__generated__/models/libraryAgent";
import { useQueryStates, parseAsString } from "nuqs";
export const TriggerAgentBanner = () => {
const [{ flowID }] = useQueryStates({
flowID: parseAsString,
});
const { data: libraryAgent } = useGetV2GetLibraryAgentByGraphId(
flowID ?? "",
{},
{
query: {
select: (x) => {
return x.data as LibraryAgent;
},
enabled: !!flowID,
},
},
);
return (
<Alert className="absolute bottom-4 left-1/2 z-20 w-auto -translate-x-1/2 select-none rounded-xlarge">
<AlertTitle>You are building a Trigger Agent</AlertTitle>
<AlertDescription>
Your agent will listen for its trigger and will run when the time is
right.
<br />
You can view its activity in your{" "}
<Link
href={
libraryAgent ? `/library/agents/${libraryAgent.id}` : "/library"
}
className="underline"
>
Agent Library
</Link>
.
</AlertDescription>
</Alert>
);
};

View File

@@ -1,16 +1,20 @@
import { useCallback } from "react";
import { Node, Edge, useReactFlow } from "@xyflow/react";
import { useReactFlow } from "@xyflow/react";
import { Key, storage } from "@/services/storage/local-storage";
import { v4 as uuidv4 } from "uuid";
import { useNodeStore } from "../../../stores/nodeStore";
import { useEdgeStore } from "../../../stores/edgeStore";
import { CustomNode } from "../nodes/CustomNode/CustomNode";
import { CustomEdge } from "../edges/CustomEdge";
interface CopyableData {
nodes: Node[];
edges: Edge[];
nodes: CustomNode[];
edges: CustomEdge[];
}
export function useCopyPaste() {
const { setNodes, addEdges, getNodes, getEdges, getViewport } =
useReactFlow();
// Only use useReactFlow for viewport (not managed by stores)
const { getViewport } = useReactFlow();
const handleCopyPaste = useCallback(
(event: KeyboardEvent) => {
@@ -26,13 +30,15 @@ export function useCopyPaste() {
if (event.ctrlKey || event.metaKey) {
// COPY: Ctrl+C or Cmd+C
if (event.key === "c" || event.key === "C") {
const selectedNodes = getNodes().filter((node) => node.selected);
const { nodes } = useNodeStore.getState();
const { edges } = useEdgeStore.getState();
const selectedNodes = nodes.filter((node) => node.selected);
const selectedNodeIds = new Set(selectedNodes.map((node) => node.id));
// Only copy edges where both source and target nodes are selected
const selectedEdges = getEdges().filter(
// Copy edges where both source and target nodes are selected
const selectedEdges = edges.filter(
(edge) =>
edge.selected &&
selectedNodeIds.has(edge.source) &&
selectedNodeIds.has(edge.target),
);
@@ -68,7 +74,7 @@ export function useCopyPaste() {
minY = Infinity,
maxX = -Infinity,
maxY = -Infinity;
copiedData.nodes.forEach((node: Node) => {
copiedData.nodes.forEach((node) => {
minX = Math.min(minX, node.position.x);
minY = Math.min(minY, node.position.y);
maxX = Math.max(maxX, node.position.x);
@@ -78,50 +84,50 @@ export function useCopyPaste() {
const offsetX = viewportCenter.x - (minX + maxX) / 2;
const offsetY = viewportCenter.y - (minY + maxY) / 2;
// Create new nodes with UNIQUE IDs using UUID
const pastedNodes = copiedData.nodes.map((node: Node) => {
const newNodeId = uuidv4(); // Generate unique UUID for each node
// Deselect existing nodes first
useNodeStore.setState((state) => ({
nodes: state.nodes.map((node) => ({ ...node, selected: false })),
}));
// Create and add new nodes with UNIQUE IDs using UUID
copiedData.nodes.forEach((node) => {
const newNodeId = uuidv4();
oldToNewIdMap[node.id] = newNodeId;
return {
const newNode: CustomNode = {
...node,
id: newNodeId, // Assign the new unique ID
selected: true, // Select the pasted nodes
id: newNodeId,
selected: true,
position: {
x: node.position.x + offsetX,
y: node.position.y + offsetY,
},
data: {
...node.data,
backend_id: undefined, // Clear backend_id so the new node.id is used when saving
status: undefined, // Clear execution status
nodeExecutionResult: undefined, // Clear execution results
},
};
useNodeStore.getState().addNode(newNode);
});
// Create new edges with updated source/target IDs
const pastedEdges = copiedData.edges.map((edge) => {
// Add edges with updated source/target IDs
const { addEdge } = useEdgeStore.getState();
copiedData.edges.forEach((edge) => {
const newSourceId = oldToNewIdMap[edge.source] ?? edge.source;
const newTargetId = oldToNewIdMap[edge.target] ?? edge.target;
return {
...edge,
id: `${newSourceId}_${edge.sourceHandle}_${newTargetId}_${edge.targetHandle}_${Date.now()}`,
addEdge({
source: newSourceId,
target: newTargetId,
};
sourceHandle: edge.sourceHandle ?? "",
targetHandle: edge.targetHandle ?? "",
data: {
...edge.data,
},
});
});
// Deselect existing nodes and add pasted nodes
setNodes((existingNodes) => [
...existingNodes.map((node) => ({ ...node, selected: false })),
...pastedNodes,
]);
addEdges(pastedEdges);
}
}
}
},
[setNodes, addEdges, getNodes, getEdges, getViewport],
[getViewport],
);
return handleCopyPaste;

View File

@@ -1,7 +1,7 @@
"use client";
import { globalRegistry } from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/OutputRenderers";
import type { OutputMetadata } from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/OutputRenderers";
import type { OutputMetadata } from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/selected-views/OutputRenderers";
import { globalRegistry } from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/selected-views/OutputRenderers";
export const TextRenderer: React.FC<{
value: any;

View File

@@ -1,25 +1,25 @@
import React, { FC } from "react";
import { Dialog } from "@/components/molecules/Dialog/Dialog";
import {
OutputActions,
OutputItem,
} from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/selected-views/OutputRenderers";
import { ScrollArea } from "@/components/__legacy__/ui/scroll-area";
import { Button } from "@/components/atoms/Button/Button";
import { Text } from "@/components/atoms/Text/Text";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/atoms/Tooltip/BaseTooltip";
import { Dialog } from "@/components/molecules/Dialog/Dialog";
import { beautifyString } from "@/lib/utils";
import {
ArrowsOutSimpleIcon,
CheckIcon,
CopyIcon,
DownloadIcon,
CheckIcon,
} from "@phosphor-icons/react";
import { Text } from "@/components/atoms/Text/Text";
import { beautifyString } from "@/lib/utils";
import { ScrollArea } from "@/components/__legacy__/ui/scroll-area";
import {
OutputItem,
OutputActions,
} from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/OutputRenderers";
import { FC } from "react";
import { useNodeDataViewer } from "./useNodeDataViewer";
interface NodeDataViewerProps {

View File

@@ -1,9 +1,9 @@
import React, { useState, useMemo } from "react";
import type { OutputMetadata } from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/OutputRenderers";
import { downloadOutputs } from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/OutputRenderers/utils/download";
import type { OutputMetadata } from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/selected-views/OutputRenderers";
import { globalRegistry } from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/selected-views/OutputRenderers";
import { downloadOutputs } from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/selected-views/OutputRenderers/utils/download";
import { useToast } from "@/components/molecules/Toast/use-toast";
import { globalRegistry } from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/OutputRenderers";
import { beautifyString } from "@/lib/utils";
import React, { useMemo, useState } from "react";
export const useNodeDataViewer = (
data: any,

View File

@@ -4,7 +4,7 @@ import { useShallow } from "zustand/react/shallow";
import { useState } from "react";
export const useNodeOutput = (nodeId: string) => {
const [isExpanded, setIsExpanded] = useState(false);
const [isExpanded, setIsExpanded] = useState(true);
const [copiedKey, setCopiedKey] = useState<string | null>(null);
const { toast } = useToast();

View File

@@ -19,6 +19,10 @@ export const BlockMenuSearch = () => {
fetchNextPage,
hasNextPage,
searchLoading,
handleAddLibraryAgent,
handleAddMarketplaceAgent,
addingLibraryAgentId,
addingMarketplaceAgentSlug,
} = useBlockMenuSearch();
const { searchQuery } = useBlockMenuStore();
@@ -63,7 +67,13 @@ export const BlockMenuSearch = () => {
image_url={data.agent_image}
creator_name={data.creator}
number_of_runs={data.runs}
loading={false}
loading={addingMarketplaceAgentSlug === data.slug}
onClick={() =>
handleAddMarketplaceAgent({
creator_name: data.creator,
slug: data.slug,
})
}
/>
);
case "block":
@@ -86,6 +96,8 @@ export const BlockMenuSearch = () => {
image_url={data.image_url}
version={data.graph_version}
edited_time={data.updated_at}
isLoading={addingLibraryAgentId === data.id}
onClick={() => handleAddLibraryAgent(data)}
/>
);

View File

@@ -1,9 +1,31 @@
import { useBlockMenuStore } from "../../../../stores/blockMenuStore";
import { useGetV2BuilderSearchInfinite } from "@/app/api/__generated__/endpoints/store/store";
import { SearchResponse } from "@/app/api/__generated__/models/searchResponse";
import { useState } from "react";
import { useAddAgentToBuilder } from "../hooks/useAddAgentToBuilder";
import { LibraryAgent } from "@/app/api/__generated__/models/libraryAgent";
import { getV2GetSpecificAgent } from "@/app/api/__generated__/endpoints/store/store";
import {
getGetV2ListLibraryAgentsQueryKey,
usePostV2AddMarketplaceAgent,
} from "@/app/api/__generated__/endpoints/library/library";
import { getGetV2GetBuilderItemCountsQueryKey } from "@/app/api/__generated__/endpoints/default/default";
import { getQueryClient } from "@/lib/react-query/queryClient";
import { useToast } from "@/components/molecules/Toast/use-toast";
import * as Sentry from "@sentry/nextjs";
export const useBlockMenuSearch = () => {
const { searchQuery } = useBlockMenuStore();
const { toast } = useToast();
const { addAgentToBuilder, addLibraryAgentToBuilder } =
useAddAgentToBuilder();
const [addingLibraryAgentId, setAddingLibraryAgentId] = useState<
string | null
>(null);
const [addingMarketplaceAgentSlug, setAddingMarketplaceAgentSlug] = useState<
string | null
>(null);
const {
data: searchData,
@@ -28,17 +50,101 @@ export const useBlockMenuSearch = () => {
},
);
const { mutateAsync: addMarketplaceAgent } = usePostV2AddMarketplaceAgent({
mutation: {
onSuccess: () => {
const queryClient = getQueryClient();
queryClient.invalidateQueries({
queryKey: getGetV2ListLibraryAgentsQueryKey(),
});
queryClient.refetchQueries({
queryKey: getGetV2GetBuilderItemCountsQueryKey(),
});
},
onError: (error) => {
Sentry.captureException(error);
toast({
title: "Failed to add agent to library",
description:
((error as any).message as string) ||
"An unexpected error occurred.",
variant: "destructive",
});
},
},
});
const allSearchData =
searchData?.pages?.flatMap((page) => {
const response = page.data as SearchResponse;
return response.items;
}) ?? [];
const handleAddLibraryAgent = async (agent: LibraryAgent) => {
setAddingLibraryAgentId(agent.id);
try {
await addLibraryAgentToBuilder(agent);
} catch (error) {
console.error("Error adding library agent:", error);
} finally {
setAddingLibraryAgentId(null);
}
};
const handleAddMarketplaceAgent = async ({
creator_name,
slug,
}: {
creator_name: string;
slug: string;
}) => {
try {
setAddingMarketplaceAgentSlug(slug);
const { data: agent, status } = await getV2GetSpecificAgent(
creator_name,
slug,
);
if (status !== 200) {
Sentry.captureException("Store listing version not found");
throw new Error("Store listing version not found");
}
const response = await addMarketplaceAgent({
data: {
store_listing_version_id: agent?.store_listing_version_id,
},
});
const libraryAgent = response.data as LibraryAgent;
addAgentToBuilder(libraryAgent);
toast({
title: "Agent Added",
description: "Agent has been added to your library and builder",
});
} catch (error) {
Sentry.captureException(error);
toast({
title: "Failed to add agent to library",
description:
((error as any).message as string) || "An unexpected error occurred.",
variant: "destructive",
});
} finally {
setAddingMarketplaceAgentSlug(null);
}
};
return {
allSearchData,
isFetchingNextPage,
fetchNextPage,
hasNextPage,
searchLoading,
handleAddLibraryAgent,
handleAddMarketplaceAgent,
addingLibraryAgentId,
addingMarketplaceAgentSlug,
};
};

View File

@@ -12,10 +12,13 @@ import { StoreAgentsResponse } from "@/lib/autogpt-server-api";
import { getQueryClient } from "@/lib/react-query/queryClient";
import * as Sentry from "@sentry/nextjs";
import { useState } from "react";
import { useAddAgentToBuilder } from "../hooks/useAddAgentToBuilder";
import { LibraryAgent } from "@/app/api/__generated__/models/libraryAgent";
export const useMarketplaceAgentsContent = () => {
const { toast } = useToast();
const [addingAgent, setAddingAgent] = useState<string | null>(null);
const { addAgentToBuilder } = useAddAgentToBuilder();
const {
data: listStoreAgents,
@@ -53,7 +56,7 @@ export const useMarketplaceAgentsContent = () => {
const status = listStoreAgents?.pages[0]?.status;
const { mutate: addMarketplaceAgent } = usePostV2AddMarketplaceAgent({
const { mutateAsync: addMarketplaceAgent } = usePostV2AddMarketplaceAgent({
mutation: {
onSuccess: () => {
const queryClient = getQueryClient();
@@ -65,6 +68,16 @@ export const useMarketplaceAgentsContent = () => {
queryKey: getGetV2GetBuilderItemCountsQueryKey(),
});
},
onError: (error) => {
Sentry.captureException(error);
toast({
title: "Failed to add agent to library",
description:
((error as any).message as string) ||
"An unexpected error occurred.",
variant: "destructive",
});
},
},
});
@@ -86,19 +99,26 @@ export const useMarketplaceAgentsContent = () => {
throw new Error("Store listing version not found");
}
addMarketplaceAgent({
const response = await addMarketplaceAgent({
data: {
store_listing_version_id: agent?.store_listing_version_id,
},
});
// Need a way to convert the library agent into block
// then add the block in builder
const libraryAgent = response.data as LibraryAgent;
addAgentToBuilder(libraryAgent);
toast({
title: "Agent Added",
description: "Agent has been added to your library and builder",
});
} catch (error) {
Sentry.captureException(error);
toast({
title: "Error",
description: "Failed to add agent to library",
title: "Failed to add agent to library",
description:
((error as any).message as string) || "An unexpected error occurred.",
variant: "destructive",
});
} finally {
setAddingAgent(null);

View File

@@ -1,22 +1,16 @@
import {
getV2GetLibraryAgent,
useGetV2ListLibraryAgentsInfinite,
} from "@/app/api/__generated__/endpoints/library/library";
import { useGetV2ListLibraryAgentsInfinite } from "@/app/api/__generated__/endpoints/library/library";
import { LibraryAgentResponse } from "@/app/api/__generated__/models/libraryAgentResponse";
import { useState } from "react";
import { convertLibraryAgentIntoCustomNode } from "../helpers";
import { useNodeStore } from "@/app/(platform)/build/stores/nodeStore";
import { LibraryAgent } from "@/app/api/__generated__/models/libraryAgent";
import { useShallow } from "zustand/react/shallow";
import { useReactFlow } from "@xyflow/react";
import { useAddAgentToBuilder } from "../hooks/useAddAgentToBuilder";
import { useToast } from "@/components/molecules/Toast/use-toast";
export const useMyAgentsContent = () => {
const [selectedAgentId, setSelectedAgentId] = useState<string | null>(null);
const [isGettingAgentDetails, setIsGettingAgentDetails] = useState(false);
const addBlock = useNodeStore(useShallow((state) => state.addBlock));
const { setViewport } = useReactFlow();
// This endpoints is not giving info about inputSchema and outputSchema
// Will create new endpoint for this
const { addLibraryAgentToBuilder } = useAddAgentToBuilder();
const { toast } = useToast();
const {
data: agents,
fetchNextPage,
@@ -58,32 +52,14 @@ export const useMyAgentsContent = () => {
setIsGettingAgentDetails(true);
try {
const response = await getV2GetLibraryAgent(agent.id);
if (!response.data) {
console.error("Failed to get agent details", selectedAgentId, agent.id);
return;
}
const { input_schema, output_schema } = response.data as LibraryAgent;
const { block, hardcodedValues } = convertLibraryAgentIntoCustomNode(
agent,
input_schema,
output_schema,
);
const customNode = addBlock(block, hardcodedValues);
setTimeout(() => {
setViewport(
{
x: -customNode.position.x * 0.8 + window.innerWidth / 2,
y: -customNode.position.y * 0.8 + (window.innerHeight - 400) / 2,
zoom: 0.8,
},
{ duration: 500 },
);
}, 50);
await addLibraryAgentToBuilder(agent);
} catch (error) {
console.error("Error adding block:", error);
toast({
title: "Failed to add agent to builder",
description:
((error as any).message as string) || "An unexpected error occurred.",
variant: "destructive",
});
} finally {
setSelectedAgentId(null);
setIsGettingAgentDetails(false);

View File

@@ -0,0 +1,52 @@
import { useNodeStore } from "@/app/(platform)/build/stores/nodeStore";
import { useShallow } from "zustand/react/shallow";
import { useReactFlow } from "@xyflow/react";
import { convertLibraryAgentIntoCustomNode } from "../helpers";
import { LibraryAgent } from "@/app/api/__generated__/models/libraryAgent";
import { getV2GetLibraryAgent } from "@/app/api/__generated__/endpoints/library/library";
export const useAddAgentToBuilder = () => {
const addBlock = useNodeStore(useShallow((state) => state.addBlock));
const { setViewport } = useReactFlow();
const addAgentToBuilder = (libraryAgent: LibraryAgent) => {
const { input_schema, output_schema } = libraryAgent;
const { block, hardcodedValues } = convertLibraryAgentIntoCustomNode(
libraryAgent,
input_schema,
output_schema,
);
const customNode = addBlock(block, hardcodedValues);
setTimeout(() => {
setViewport(
{
x: -customNode.position.x * 0.8 + window.innerWidth / 2,
y: -customNode.position.y * 0.8 + (window.innerHeight - 400) / 2,
zoom: 0.8,
},
{ duration: 500 },
);
}, 50);
return customNode;
};
const addLibraryAgentToBuilder = async (agent: LibraryAgent) => {
const response = await getV2GetLibraryAgent(agent.id);
if (!response.data) {
throw new Error("Failed to get agent details");
}
const libraryAgent = response.data as LibraryAgent;
return addAgentToBuilder(libraryAgent);
};
return {
addAgentToBuilder,
addLibraryAgentToBuilder,
};
};

View File

@@ -1,27 +1,27 @@
import type { OutputMetadata } from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/selected-views/OutputRenderers";
import {
globalRegistry,
OutputActions,
OutputItem,
} from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/selected-views/OutputRenderers";
import { beautifyString } from "@/lib/utils";
import { Flag, useGetFlag } from "@/services/feature-flags/use-get-flag";
import { Clipboard, Maximize2 } from "lucide-react";
import React, { FC, useMemo, useState } from "react";
import { Button } from "../../../../../components/__legacy__/ui/button";
import { ContentRenderer } from "../../../../../components/__legacy__/ui/render";
import { beautifyString } from "@/lib/utils";
import { Clipboard, Maximize2 } from "lucide-react";
import { useToast } from "../../../../../components/molecules/Toast/use-toast";
import { Switch } from "../../../../../components/atoms/Switch/Switch";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "../../../../../components/__legacy__/ui/dialog";
import { ContentRenderer } from "../../../../../components/__legacy__/ui/render";
import { ScrollArea } from "../../../../../components/__legacy__/ui/scroll-area";
import { Separator } from "../../../../../components/__legacy__/ui/separator";
import { Flag, useGetFlag } from "@/services/feature-flags/use-get-flag";
import {
globalRegistry,
OutputItem,
OutputActions,
} from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/OutputRenderers";
import type { OutputMetadata } from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/OutputRenderers";
import { Switch } from "../../../../../components/atoms/Switch/Switch";
import { useToast } from "../../../../../components/molecules/Toast/use-toast";
interface ExpandableOutputDialogProps {
isOpen: boolean;

View File

@@ -2,14 +2,33 @@ import {
ConnectionData,
CustomNodeData,
} from "@/app/(platform)/build/components/legacy-builder/CustomNode/CustomNode";
import { CredentialsInput } from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/CredentialsInputs/CredentialsInputs";
import { CredentialsInput } from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/modals/CredentialsInputs/CredentialsInputs";
import { Button } from "@/components/__legacy__/ui/button";
import { Calendar } from "@/components/__legacy__/ui/calendar";
import { LocalValuedInput } from "@/components/__legacy__/ui/input";
import {
MultiSelector,
MultiSelectorContent,
MultiSelectorInput,
MultiSelectorItem,
MultiSelectorList,
MultiSelectorTrigger,
} from "@/components/__legacy__/ui/multiselect";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/__legacy__/ui/popover";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/__legacy__/ui/select";
import { Switch } from "@/components/atoms/Switch/Switch";
import { GoogleDrivePickerInput } from "@/components/contextual/GoogleDrivePicker/GoogleDrivePickerInput";
import { NodeTableInput } from "@/components/node-table-input";
import {
BlockIOArraySubSchema,
BlockIOBooleanSubSchema,
@@ -39,25 +58,6 @@ import React, {
useRef,
useState,
} from "react";
import { Button } from "@/components/__legacy__/ui/button";
import { LocalValuedInput } from "@/components/__legacy__/ui/input";
import {
MultiSelector,
MultiSelectorContent,
MultiSelectorInput,
MultiSelectorItem,
MultiSelectorList,
MultiSelectorTrigger,
} from "@/components/__legacy__/ui/multiselect";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/__legacy__/ui/select";
import { Switch } from "@/components/atoms/Switch/Switch";
import { NodeTableInput } from "@/components/node-table-input";
import NodeHandle from "./NodeHandle";
type NodeObjectInputTreeProps = {

View File

@@ -13,6 +13,13 @@ import { useHistoryStore } from "./historyStore";
import { useEdgeStore } from "./edgeStore";
import { BlockUIType } from "../components/types";
// Minimum movement (in pixels) required before logging position change to history
// Prevents spamming history with small movements when clicking on inputs inside blocks
const MINIMUM_MOVE_BEFORE_LOG = 50;
// Track initial positions when drag starts (outside store to avoid re-renders)
const dragStartPositions: Record<string, XYPosition> = {};
type NodeStore = {
nodes: CustomNode[];
nodeCounter: number;
@@ -44,6 +51,7 @@ type NodeStore = {
) => void;
getNodeExecutionResult: (nodeId: string) => NodeExecutionResult | undefined;
getNodeBlockUIType: (nodeId: string) => BlockUIType;
hasWebhookNodes: () => boolean;
};
export const useNodeStore = create<NodeStore>((set, get) => ({
@@ -60,12 +68,44 @@ export const useNodeStore = create<NodeStore>((set, get) => ({
nodes: get().nodes,
edges: useEdgeStore.getState().edges,
};
const shouldTrack = changes.some(
(change) =>
change.type === "remove" ||
change.type === "add" ||
(change.type === "position" && change.dragging === false),
// Track initial positions when drag starts
changes.forEach((change) => {
if (change.type === "position" && change.dragging === true) {
if (!dragStartPositions[change.id]) {
const node = get().nodes.find((n) => n.id === change.id);
if (node) {
dragStartPositions[change.id] = { ...node.position };
}
}
}
});
// Check if we should track this change in history
let shouldTrack = changes.some(
(change) => change.type === "remove" || change.type === "add",
);
// For position changes, only track if movement exceeds threshold
if (!shouldTrack) {
changes.forEach((change) => {
if (change.type === "position" && change.dragging === false) {
const startPos = dragStartPositions[change.id];
if (startPos && change.position) {
const distanceMoved = Math.sqrt(
Math.pow(change.position.x - startPos.x, 2) +
Math.pow(change.position.y - startPos.y, 2),
);
if (distanceMoved > MINIMUM_MOVE_BEFORE_LOG) {
shouldTrack = true;
}
}
// Clean up tracked position after drag ends
delete dragStartPositions[change.id];
}
});
}
set((state) => ({
nodes: applyNodeChanges(changes, state.nodes),
}));
@@ -163,9 +203,10 @@ export const useNodeStore = create<NodeStore>((set, get) => ({
block_id: node.data.block_id,
input_default: node.data.hardcodedValues,
metadata: {
// TODO: Add more metadata
position: node.position,
customized_name: node.data.metadata?.customized_name,
...(node.data.metadata?.customized_name !== undefined && {
customized_name: node.data.metadata.customized_name,
}),
},
};
},
@@ -203,4 +244,9 @@ export const useNodeStore = create<NodeStore>((set, get) => ({
BlockUIType.STANDARD
);
},
hasWebhookNodes: () => {
return get().nodes.some((n) =>
[BlockUIType.WEBHOOK, BlockUIType.WEBHOOK_MANUAL].includes(n.data.uiType),
);
},
}));

View File

@@ -1,11 +1,11 @@
import { useEffect, useRef } from "react";
import { CredentialsInput } from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/modals/CredentialsInputs/CredentialsInputs";
import { Card } from "@/components/atoms/Card/Card";
import { Text } from "@/components/atoms/Text/Text";
import { KeyIcon, CheckIcon, WarningIcon } from "@phosphor-icons/react";
import { cn } from "@/lib/utils";
import { useChatCredentialsSetup } from "./useChatCredentialsSetup";
import { CredentialsInput } from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/CredentialsInputs/CredentialsInputs";
import type { BlockIOCredentialsSubSchema } from "@/lib/autogpt-server-api";
import { cn } from "@/lib/utils";
import { CheckIcon, KeyIcon, WarningIcon } from "@phosphor-icons/react";
import { useEffect, useRef } from "react";
import { useChatCredentialsSetup } from "./useChatCredentialsSetup";
export interface CredentialInfo {
provider: string;

View File

@@ -1,126 +0,0 @@
"use client";
import { Button } from "@/components/atoms/Button/Button";
import { Breadcrumbs } from "@/components/molecules/Breadcrumbs/Breadcrumbs";
import { ErrorCard } from "@/components/molecules/ErrorCard/ErrorCard";
import { PlusIcon } from "@phosphor-icons/react";
import { useEffect } from "react";
import { AgentRunsLoading } from "./components/AgentRunsLoading";
import { EmptyAgentRuns } from "./components/EmptyAgentRuns/EmptyAgentRuns";
import { RunAgentModal } from "./components/RunAgentModal/RunAgentModal";
import { RunsSidebar } from "./components/RunsSidebar/RunsSidebar";
import { SelectedRunView } from "./components/SelectedRunView/SelectedRunView";
import { SelectedScheduleView } from "./components/SelectedScheduleView/SelectedScheduleView";
import { useAgentRunsView } from "./useAgentRunsView";
export function AgentRunsView() {
const {
agent,
hasAnyItems,
showSidebarLayout,
ready,
error,
agentId,
selectedRun,
handleSelectRun,
handleCountsChange,
handleClearSelectedRun,
} = useAgentRunsView();
useEffect(() => {
if (agent) {
document.title = `${agent.name} - Library - AutoGPT Platform`;
}
}, [agent]);
if (error) {
return (
<ErrorCard
isSuccess={false}
responseError={error || undefined}
context="agent"
onRetry={() => window.location.reload()}
/>
);
}
if (!ready || !agent) {
return <AgentRunsLoading />;
}
return (
<div
className={
showSidebarLayout
? "grid h-screen grid-cols-1 gap-0 pt-3 md:gap-4 lg:grid-cols-[25%_70%]"
: "grid h-screen grid-cols-1 gap-0 pt-3 md:gap-4"
}
>
<div className={showSidebarLayout ? "p-4 pl-5" : "hidden p-4 pl-5"}>
<div className="mb-4">
<RunAgentModal
triggerSlot={
<Button variant="primary" size="large" className="w-full">
<PlusIcon size={20} /> New Run
</Button>
}
agent={agent}
agentId={agent.id.toString()}
onRunCreated={(execution) => handleSelectRun(execution.id)}
onScheduleCreated={(schedule) =>
handleSelectRun(`schedule:${schedule.id}`)
}
/>
</div>
<RunsSidebar
agent={agent}
selectedRunId={selectedRun}
onSelectRun={handleSelectRun}
onCountsChange={handleCountsChange}
/>
</div>
{/* Main Content - 70% */}
<div className="p-4">
<div className={!showSidebarLayout ? "px-2" : ""}>
<Breadcrumbs
items={[
{ name: "My Library", link: "/library" },
{ name: agent.name, link: `/library/agents/${agentId}` },
]}
/>
</div>
<div className="mt-1">
{selectedRun ? (
selectedRun.startsWith("schedule:") ? (
<SelectedScheduleView
agent={agent}
scheduleId={selectedRun.replace("schedule:", "")}
onClearSelectedRun={handleClearSelectedRun}
/>
) : (
<SelectedRunView
agent={agent}
runId={selectedRun}
onSelectRun={handleSelectRun}
onClearSelectedRun={handleClearSelectedRun}
/>
)
) : hasAnyItems ? (
<div className="text-gray-600">
Select a run to view its details
</div>
) : (
<EmptyAgentRuns
agentName={agent.name}
creatorName={agent.creator_name || "Unknown"}
description={agent.description}
agent={agent}
/>
)}
</div>
</div>
</div>
);
}

View File

@@ -1,70 +0,0 @@
import { ShowMoreText } from "@/components/molecules/ShowMoreText/ShowMoreText";
import { RunDetailCard } from "../RunDetailCard/RunDetailCard";
import { Text } from "@/components/atoms/Text/Text";
import { RunAgentModal } from "../RunAgentModal/RunAgentModal";
import { LibraryAgent } from "@/app/api/__generated__/models/libraryAgent";
import { Button } from "@/components/atoms/Button/Button";
import { PlusIcon } from "@phosphor-icons/react";
type Props = {
agentName: string;
creatorName: string;
description: string;
agent: LibraryAgent;
};
export function EmptyAgentRuns({
agentName,
creatorName,
description,
agent,
}: Props) {
const isUnknownCreator = creatorName === "Unknown";
return (
<div className="mt-6 px-2">
<RunDetailCard className="relative min-h-[70vh]">
<div className="absolute left-1/2 top-1/2 flex w-[80%] -translate-x-1/2 -translate-y-1/2 flex-col gap-6 md:w-[60%] lg:w-auto">
<div className="flex flex-col gap-4">
<div className="flex flex-col gap-2">
<Text
variant="h3"
className="truncate text-ellipsis !font-normal"
>
{agentName}
</Text>
{!isUnknownCreator ? (
<Text variant="body-medium">by {creatorName}</Text>
) : null}
</div>
{description ? (
<ShowMoreText
previewLimit={80}
variant="small"
className="mt-4 !text-zinc-700"
>
{description}
</ShowMoreText>
) : null}
</div>
<div className="flex flex-col gap-4">
<Text variant="h4">You dont have any runs</Text>
<Text variant="large">
Get started with creating a run, and youll see information here
</Text>
</div>
<RunAgentModal
triggerSlot={
<Button variant="primary" size="large" className="w-full">
<PlusIcon size={20} /> New Run
</Button>
}
agent={agent}
agentId={agent.id.toString()}
/>
</div>
</RunDetailCard>
</div>
);
}

View File

@@ -0,0 +1,128 @@
"use client";
import { Button } from "@/components/atoms/Button/Button";
import { Breadcrumbs } from "@/components/molecules/Breadcrumbs/Breadcrumbs";
import { ErrorCard } from "@/components/molecules/ErrorCard/ErrorCard";
import { PlusIcon } from "@phosphor-icons/react";
import { useEffect } from "react";
import { RunAgentModal } from "./components/modals/RunAgentModal/RunAgentModal";
import { AgentRunsLoading } from "./components/other/AgentRunsLoading";
import { EmptyAgentRuns } from "./components/other/EmptyAgentRuns";
import { SelectedRunView } from "./components/selected-views/SelectedRunView/SelectedRunView";
import { SelectedScheduleView } from "./components/selected-views/SelectedScheduleView/SelectedScheduleView";
import { AgentRunsLists } from "./components/sidebar/AgentRunsLists/AgentRunsLists";
import { useNewAgentLibraryView } from "./useNewAgentLibraryView";
export function NewAgentLibraryView() {
const {
agent,
hasAnyItems,
ready,
error,
agentId,
selectedRun,
sidebarLoading,
handleSelectRun,
handleCountsChange,
handleClearSelectedRun,
} = useNewAgentLibraryView();
useEffect(() => {
if (agent) {
document.title = `${agent.name} - Library - AutoGPT Platform`;
}
}, [agent]);
if (error) {
return (
<ErrorCard
isSuccess={false}
responseError={error || undefined}
context="agent"
onRetry={() => window.location.reload()}
/>
);
}
if (!ready || !agent) {
return <AgentRunsLoading />;
}
const shouldShowSidebar = sidebarLoading || hasAnyItems;
return (
<div
className={
shouldShowSidebar
? "grid h-full grid-cols-1 gap-0 pt-3 md:gap-4 lg:grid-cols-[25%_70%]"
: "grid h-full grid-cols-1 gap-0 pt-3 md:gap-4"
}
>
{shouldShowSidebar && (
<div className="p-4 pl-5">
<div className="mb-4">
<RunAgentModal
triggerSlot={
<Button variant="primary" size="large" className="w-full">
<PlusIcon size={20} /> New Run
</Button>
}
agent={agent}
agentId={agent.id.toString()}
onRunCreated={(execution) => handleSelectRun(execution.id)}
onScheduleCreated={(schedule) =>
handleSelectRun(`schedule:${schedule.id}`)
}
/>
</div>
<AgentRunsLists
agent={agent}
selectedRunId={selectedRun}
onSelectRun={handleSelectRun}
onCountsChange={handleCountsChange}
/>
</div>
)}
{/* Main Content - 70% */}
<div className="flex min-h-0 flex-col gap-4 p-4">
<div className={!shouldShowSidebar ? "px-2" : ""}>
<Breadcrumbs
items={[
{ name: "My Library", link: "/library" },
{ name: agent.name, link: `/library/agents/${agentId}` },
]}
/>
</div>
<div className="flex min-h-0 flex-1 flex-col">
{selectedRun ? (
selectedRun.startsWith("schedule:") ? (
<SelectedScheduleView
agent={agent}
scheduleId={selectedRun.replace("schedule:", "")}
onClearSelectedRun={handleClearSelectedRun}
/>
) : (
<SelectedRunView
agent={agent}
runId={selectedRun}
onSelectRun={handleSelectRun}
onClearSelectedRun={handleClearSelectedRun}
/>
)
) : sidebarLoading ? (
// Show loading state while sidebar is loading to prevent flash of empty state
<div className="text-gray-600">Loading runs...</div>
) : hasAnyItems ? (
<div className="text-gray-600">
Select a run to view its details
</div>
) : (
<EmptyAgentRuns agent={agent} />
)}
</div>
</div>
</div>
);
}

View File

@@ -1,4 +1,3 @@
import { Button } from "@/components/atoms/Button/Button";
import {
IconKey,
IconKeyPlus,
@@ -12,6 +11,8 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/__legacy__/ui/select";
import { Button } from "@/components/atoms/Button/Button";
import { InformationTooltip } from "@/components/molecules/InformationTooltip/InformationTooltip";
import useCredentials from "@/hooks/useCredentials";
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
import {
@@ -31,11 +32,10 @@ import {
FaMedium,
FaTwitter,
} from "react-icons/fa";
import { APIKeyCredentialsModal } from "../APIKeyCredentialsModal/APIKeyCredentialsModal";
import { HostScopedCredentialsModal } from "../HotScopedCredentialsModal/HotScopedCredentialsModal";
import { OAuthFlowWaitingModal } from "../OAuthWaitingModal/OAuthWaitingModal";
import { PasswordCredentialsModal } from "../PasswordCredentialsModal/PasswordCredentialsModal";
import { InformationTooltip } from "@/components/molecules/InformationTooltip/InformationTooltip";
import { APIKeyCredentialsModal } from "./APIKeyCredentialsModal/APIKeyCredentialsModal";
import { HostScopedCredentialsModal } from "./HotScopedCredentialsModal/HotScopedCredentialsModal";
import { OAuthFlowWaitingModal } from "./OAuthWaitingModal/OAuthWaitingModal";
import { PasswordCredentialsModal } from "./PasswordCredentialsModal/PasswordCredentialsModal";
const fallbackIcon = FaKey;

View File

@@ -1,21 +1,21 @@
"use client";
import { Dialog } from "@/components/molecules/Dialog/Dialog";
import { Button } from "@/components/atoms/Button/Button";
import { useState } from "react";
import { LibraryAgent } from "@/app/api/__generated__/models/libraryAgent";
import { useAgentRunModal } from "./useAgentRunModal";
import { ModalHeader } from "./components/ModalHeader/ModalHeader";
import { AgentCostSection } from "./components/AgentCostSection/AgentCostSection";
import { AgentSectionHeader } from "./components/AgentSectionHeader/AgentSectionHeader";
import { ModalRunSection } from "./components/ModalRunSection/ModalRunSection";
import { RunAgentModalContextProvider } from "./context";
import { AgentDetails } from "./components/AgentDetails/AgentDetails";
import { RunActions } from "./components/RunActions/RunActions";
import { ScheduleAgentModal } from "../ScheduleAgentModal/ScheduleAgentModal";
import { AlarmIcon } from "@phosphor-icons/react";
import { GraphExecutionMeta } from "@/app/api/__generated__/models/graphExecutionMeta";
import { GraphExecutionJobInfo } from "@/app/api/__generated__/models/graphExecutionJobInfo";
import { GraphExecutionMeta } from "@/app/api/__generated__/models/graphExecutionMeta";
import { LibraryAgent } from "@/app/api/__generated__/models/libraryAgent";
import { Button } from "@/components/atoms/Button/Button";
import { Dialog } from "@/components/molecules/Dialog/Dialog";
import { AlarmIcon } from "@phosphor-icons/react";
import { useState } from "react";
import { ScheduleAgentModal } from "../ScheduleAgentModal/ScheduleAgentModal";
import { AgentCostSection } from "./components/AgentCostSection/AgentCostSection";
import { AgentDetails } from "./components/AgentDetails/AgentDetails";
import { AgentSectionHeader } from "./components/AgentSectionHeader/AgentSectionHeader";
import { ModalHeader } from "./components/ModalHeader/ModalHeader";
import { ModalRunSection } from "./components/ModalRunSection/ModalRunSection";
import { RunActions } from "./components/RunActions/RunActions";
import { RunAgentModalContextProvider } from "./context";
import { useAgentRunModal } from "./useAgentRunModal";
interface Props {
triggerSlot: React.ReactNode;

View File

@@ -1,13 +1,13 @@
import { WebhookTriggerBanner } from "../WebhookTriggerBanner/WebhookTriggerBanner";
import { CredentialsInput } from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/modals/CredentialsInputs/CredentialsInputs";
import { Input } from "@/components/atoms/Input/Input";
import { CredentialsInput } from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/CredentialsInputs/CredentialsInputs";
import { useRunAgentModalContext } from "../../context";
import { RunAgentInputs } from "../../../RunAgentInputs/RunAgentInputs";
import { InfoIcon } from "@phosphor-icons/react";
import { Text } from "@/components/atoms/Text/Text";
import { toDisplayName } from "@/providers/agent-credentials/helper";
import { getCredentialTypeDisplayName } from "./helpers";
import { InformationTooltip } from "@/components/molecules/InformationTooltip/InformationTooltip";
import { toDisplayName } from "@/providers/agent-credentials/helper";
import { InfoIcon } from "@phosphor-icons/react";
import { RunAgentInputs } from "../../../RunAgentInputs/RunAgentInputs";
import { useRunAgentModalContext } from "../../context";
import { WebhookTriggerBanner } from "../WebhookTriggerBanner/WebhookTriggerBanner";
import { getCredentialTypeDisplayName } from "./helpers";
export function ModalRunSection() {
const {

View File

@@ -0,0 +1,106 @@
import { LibraryAgent } from "@/app/api/__generated__/models/libraryAgent";
import { Button } from "@/components/atoms/Button/Button";
import { Link } from "@/components/atoms/Link/Link";
import { Text } from "@/components/atoms/Text/Text";
import { ShowMoreText } from "@/components/molecules/ShowMoreText/ShowMoreText";
import { formatDate } from "@/lib/utils/time";
import { RunAgentModal } from "../modals/RunAgentModal/RunAgentModal";
import { RunDetailCard } from "../selected-views/RunDetailCard/RunDetailCard";
import { EmptyRunsIllustration } from "./EmptyRunsIllustration";
type Props = {
agent: LibraryAgent;
};
export function EmptyAgentRuns({ agent }: Props) {
const isPublished = Boolean(agent.marketplace_listing);
const createdAt = formatDate(agent.created_at);
const updatedAt = formatDate(agent.updated_at);
const isUpdated = updatedAt !== createdAt;
return (
<div className="min-h-0 flex-1 flex-col flex-nowrap gap-2 px-2 lg:flex lg:flex-row">
<RunDetailCard className="relative flex min-h-0 flex-1 flex-col overflow-hidden">
<div className="flex flex-1 flex-col items-center justify-center gap-0">
<EmptyRunsIllustration className="-mt-20" />
<div className="flex flex-col items-center gap-12">
<div className="flex items-center justify-between gap-2">
<div className="flex flex-col items-center gap-2">
<Text variant="h3" className="text-center text-[1.375rem]">
Ready to get started?
</Text>
<Text variant="large" className="text-center">
Run your agent and this space will fill with your agent&apos;s
activity
</Text>
</div>
</div>
<RunAgentModal
triggerSlot={
<Button
variant="primary"
size="large"
className="inline-flex w-[19.75rem]"
>
Setup your task
</Button>
}
agent={agent}
agentId={agent.id.toString()}
/>
</div>
</div>
</RunDetailCard>
{isPublished ? (
<div className="mt-4 flex flex-col gap-10 rounded-large border border-zinc-200 p-6 lg:mt-0 lg:w-[29.5rem]">
<Text variant="label" className="text-zinc-500">
About this agent
</Text>
<div className="flex flex-col gap-2">
<Text variant="h4">{agent.name}</Text>
<Text variant="body">
by{" "}
<Link
href={`/marketplace/creator/${agent.marketplace_listing?.creator.slug}`}
variant="secondary"
>
{agent.marketplace_listing?.creator.name}
</Link>
</Text>
</div>
<ShowMoreText previewLimit={170} variant="body" className="-mt-4">
{agent.description ||
`Note: If you're using Docker Compose watch mode (docker compose watch), it will automatically rebuild on file changes. Since you're using docker compose up -d, manual rebuilds are needed.
You can test the endpoint from your frontend; it should return the marketplace_listing field when an agent has been published, or null if it hasn't.`}
</ShowMoreText>
<div className="flex flex-col gap-4">
<div className="flex items-center gap-20">
<div className="flex flex-col gap-2">
<Text variant="body-medium" className="text-black">
Agent created on
</Text>
<Text variant="body">{createdAt}</Text>
</div>
{isUpdated ? (
<div className="flex flex-col gap-2">
<Text variant="body-medium" className="text-black">
Agent updated on
</Text>
<Text variant="body">{updatedAt}</Text>
</div>
) : null}
</div>
<div className="mt-4 flex items-center gap-2">
<Button variant="secondary" size="small">
Edit agent
</Button>
<Button variant="secondary" size="small">
Export agent to file
</Button>
</div>
</div>
</div>
) : null}
</div>
);
}

View File

@@ -0,0 +1,746 @@
type Props = {
className?: string;
};
export function EmptyRunsIllustration({ className }: Props) {
return (
<div className={className}>
<svg
width="400"
height="400"
viewBox="0 0 400 400"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M308.8 232.72L344 313.68H246.88L256.08 214.08H295.44L308.8 232.72Z"
fill="#236FE7"
/>
<path
d="M344 313.92H246.88H246.72C246.72 313.92 246.72 313.84 246.72 313.76L255.92 214.16C255.92 214 256 213.92 256.16 213.92H295.52C295.52 213.92 295.68 213.92 295.68 214L308.96 232.56L344.16 313.52C344.16 313.52 344.16 313.68 344.16 313.76C344.16 313.76 344.08 313.84 343.92 313.84L344 313.92ZM247.12 313.44H343.6L308.48 232.8L295.28 214.32H256.24L247.12 313.44Z"
fill="#101720"
/>
<path
d="M280.16 269.12C289.52 302.72 299.12 313.68 299.12 313.68H272.08L280.16 269.12Z"
fill="#101720"
/>
<path
d="M299.12 313.92H272.08C272.08 313.92 271.92 313.92 271.92 313.84V313.68L280 269.12C280 269.04 280.08 268.96 280.24 268.96C280.32 268.96 280.48 268.96 280.48 269.12C289.68 302.24 299.28 313.52 299.36 313.6C299.36 313.6 299.36 313.76 299.36 313.84C299.36 313.92 299.2 314 299.12 314V313.92ZM272.4 313.44H298.64C296.88 311.2 288.48 299.28 280.24 270.16L272.4 313.44Z"
fill="#101720"
/>
<path
d="M131.92 289.68L100.64 299.28L56 296.16L87.28 286.56L131.92 289.68Z"
fill="#FFFFFE"
/>
<path
d="M100.64 299.52L56 296.4C55.92 296.4 55.76 296.32 55.76 296.16C55.76 296.08 55.76 295.92 55.92 295.92L87.2 286.32C87.2 286.32 87.2 286.32 87.28 286.32L131.92 289.44C132 289.44 132.16 289.52 132.16 289.68C132.16 289.76 132.16 289.92 132 289.92L100.72 299.52H100.64ZM57.28 296L100.56 299.04L130.56 289.84L87.28 286.8L57.28 296Z"
fill="#101720"
/>
<path
d="M163.2 280.08L131.92 289.68L87.2799 286.56L118.56 276.96L163.2 280.08Z"
fill="#FFFFFE"
/>
<path
d="M131.92 289.92L87.2 286.8C87.12 286.8 86.96 286.72 86.96 286.56C86.96 286.48 86.96 286.32 87.12 286.32L118.4 276.72C118.4 276.72 118.4 276.72 118.48 276.72L163.12 279.84C163.2 279.84 163.36 279.92 163.36 280.08C163.36 280.16 163.36 280.32 163.2 280.32L131.92 289.92ZM88.56 286.4L131.92 289.44L161.92 280.24L118.64 277.2L88.64 286.4H88.56Z"
fill="#101720"
/>
<path
d="M239.2 273.6L207.84 283.2L163.2 280.08L194.48 270.48L239.2 273.6Z"
fill="#FFFFFE"
/>
<path
d="M207.84 283.44L163.2 280.32C163.12 280.32 162.96 280.24 162.96 280.08C162.96 280 162.96 279.84 163.12 279.84L194.4 270.24C194.4 270.24 194.4 270.24 194.48 270.24L239.12 273.36C239.2 273.36 239.36 273.44 239.36 273.6C239.36 273.76 239.36 273.84 239.2 273.84L207.92 283.44H207.84ZM164.56 279.92L207.84 282.96L237.84 273.76L194.48 270.72L164.48 279.92H164.56Z"
fill="#101720"
/>
<path
d="M194.48 270.48L163.2 280.08L118.56 276.96L149.92 267.36L194.48 270.48Z"
fill="#FFFFFE"
/>
<path
d="M163.2 280.32L118.56 277.2C118.48 277.2 118.32 277.12 118.32 276.96C118.32 276.88 118.32 276.72 118.48 276.72L149.76 267.12C149.76 267.12 149.76 267.12 149.84 267.12L194.48 270.24C194.56 270.24 194.72 270.32 194.72 270.48C194.72 270.56 194.72 270.72 194.56 270.72L163.28 280.32H163.2ZM119.92 276.8L163.2 279.84L193.2 270.64L149.92 267.6L119.92 276.8Z"
fill="#101720"
/>
<path
d="M283.84 276.72L252.48 286.32L207.84 283.2L239.2 273.6L283.84 276.72Z"
fill="#FFFFFE"
/>
<path
d="M252.48 286.56L207.84 283.44C207.76 283.44 207.6 283.36 207.6 283.2C207.6 283.04 207.6 282.96 207.76 282.96L239.04 273.36L283.68 276.48C283.76 276.48 283.92 276.56 283.92 276.72C283.92 276.88 283.92 276.96 283.76 276.96L252.48 286.56ZM209.2 283.04L252.48 286.08L282.48 276.88L239.2 273.84L209.2 283.04Z"
fill="#101720"
/>
<path
d="M252.48 286.32L221.2 295.92L176.56 292.8L207.84 283.2L252.48 286.32Z"
fill="#FFFFFE"
/>
<path
d="M221.2 296.16L176.56 293.04C176.48 293.04 176.32 292.96 176.32 292.8C176.32 292.72 176.32 292.56 176.48 292.56L207.76 282.96L252.4 286.08C252.48 286.08 252.64 286.16 252.64 286.32C252.64 286.48 252.64 286.56 252.48 286.56L221.2 296.16ZM177.84 292.64L221.12 295.68L251.12 286.48L207.76 283.44L177.76 292.64H177.84Z"
fill="#101720"
/>
<path
d="M221.2 295.92V334.08L189.92 343.44V305.52L221.2 295.92Z"
fill="#FF9C0F"
/>
<path
d="M189.92 343.68C189.92 343.68 189.84 343.68 189.76 343.68C189.76 343.68 189.68 343.6 189.68 343.52V305.6C189.68 305.52 189.68 305.44 189.84 305.36L221.12 295.76C221.12 295.76 221.28 295.76 221.36 295.76C221.36 295.76 221.44 295.84 221.44 295.92V334.08C221.44 334.16 221.44 334.24 221.28 334.32L190 343.68H189.92ZM190.16 305.68V343.04L220.96 333.84V296.16L190.16 305.6V305.68Z"
fill="#101720"
/>
<path
d="M252.48 286.32V324.48L221.2 334.08V295.92L252.48 286.32Z"
fill="#FF9C0F"
/>
<path
d="M221.2 334.32C221.2 334.32 221.12 334.32 221.04 334.32C221.04 334.32 220.96 334.24 220.96 334.16V296C220.96 295.92 220.96 295.84 221.12 295.76L252.4 286.16C252.4 286.16 252.56 286.16 252.64 286.16C252.64 286.16 252.72 286.24 252.72 286.32V324.48C252.72 324.56 252.72 324.64 252.56 324.72L221.28 334.32H221.2ZM221.44 296.08V333.76L252.24 324.32V286.64L221.44 296.08Z"
fill="#101720"
/>
<path
d="M283.84 276.72V314.88L252.48 324.48V286.32L283.84 276.72Z"
fill="#FF9C0F"
/>
<path
d="M252.48 324.72C252.48 324.72 252.4 324.72 252.32 324.72C252.32 324.72 252.24 324.64 252.24 324.56V286.4C252.24 286.32 252.24 286.24 252.4 286.16L283.68 276.56C283.68 276.56 283.84 276.56 283.92 276.56C283.92 276.56 284 276.64 284 276.72V314.88C284 314.96 284 315.04 283.84 315.12L252.56 324.72H252.48ZM252.72 286.48V324.16L283.52 314.72V277.04L252.72 286.48Z"
fill="#101720"
/>
<path
d="M100.64 299.28V337.44L56 334.32V296.16L100.64 299.28Z"
fill="#F1EBFE"
/>
<path
d="M100.64 337.68L56 334.56C55.84 334.56 55.76 334.48 55.76 334.32V296.16V296C55.76 296 55.84 296 55.92 296L100.56 299.12C100.72 299.12 100.8 299.2 100.8 299.36V337.52V337.68C100.8 337.68 100.72 337.68 100.64 337.68ZM56.24 334.08L100.4 337.12V299.44L56.24 296.32V334V334.08Z"
fill="#101720"
/>
<path
d="M145.28 302.16V340.32L100.64 337.2V299.04L145.28 302.16Z"
fill="#F1EBFE"
/>
<path
d="M145.28 340.56L100.64 337.44C100.48 337.44 100.4 337.36 100.4 337.2V299.04C100.4 298.88 100.48 298.8 100.64 298.8L145.28 301.92C145.44 301.92 145.52 302 145.52 302.16V340.32V340.48C145.52 340.48 145.44 340.48 145.36 340.48L145.28 340.56ZM100.88 336.96L145.04 340.08V302.4L100.88 299.36V337.04V336.96Z"
fill="#101720"
/>
<path
d="M189.92 305.28V343.44L145.28 340.32V302.16L189.92 305.28Z"
fill="#F1EBFE"
/>
<path
d="M189.92 343.68L145.28 340.56C145.12 340.56 145.04 340.48 145.04 340.32V302.16V302C145.04 302 145.12 302 145.2 302L189.84 305.12C190 305.12 190.08 305.2 190.08 305.36V343.52V343.68C190.08 343.68 190 343.68 189.92 343.68ZM145.52 340.08L189.68 343.2V305.52L145.52 302.48V340.16V340.08Z"
fill="#101720"
/>
<path
d="M176.56 292.8L145.28 302.4L100.64 299.28L131.92 289.68L176.56 292.8Z"
fill="#FFFFFE"
/>
<path
d="M145.28 302.64L100.64 299.52C100.56 299.52 100.4 299.44 100.4 299.28C100.4 299.2 100.4 299.04 100.56 299.04L131.84 289.44L176.48 292.56C176.56 292.56 176.72 292.64 176.72 292.8C176.72 292.88 176.72 293.04 176.56 293.04L145.28 302.64ZM101.92 299.12L145.2 302.16L175.2 292.96L131.92 289.92L101.92 299.12Z"
fill="#101720"
/>
<path
d="M194.48 270.72C194.4 270.72 194.32 270.72 194.24 270.56C194.24 270.48 194.24 270.32 194.32 270.24C194.4 270.24 194.56 270.24 194.64 270.32C194.64 270.4 194.64 270.56 194.56 270.64C194.56 270.64 194.56 270.64 194.48 270.64V270.72Z"
fill="#101720"
/>
<path
d="M145.28 302.64L100.64 299.52C100.56 299.52 100.4 299.44 100.4 299.28C100.4 299.2 100.4 299.04 100.56 299.04L131.84 289.44L176.48 292.56C176.56 292.56 176.72 292.64 176.72 292.8C176.72 292.88 176.72 293.04 176.56 293.04L145.28 302.64ZM101.92 299.12L145.2 302.16L175.2 292.96L131.92 289.92L101.92 299.12Z"
fill="#101720"
/>
<path
d="M194.48 270.72C194.4 270.72 194.32 270.72 194.24 270.56C194.24 270.48 194.24 270.32 194.32 270.24C194.4 270.24 194.56 270.24 194.64 270.32C194.64 270.4 194.64 270.56 194.56 270.64C194.56 270.64 194.56 270.64 194.48 270.64V270.72Z"
fill="#101720"
/>
<path
d="M221.2 295.92L189.92 305.52L145.28 302.4L176.56 292.8L221.2 295.92Z"
fill="#FFFFFE"
/>
<path
d="M207.84 283.2L176.56 292.8L131.92 289.68L163.2 280.08L207.84 283.2Z"
fill="#FFFFFE"
/>
<path
d="M189.92 305.76L145.28 302.64C145.2 302.64 145.04 302.56 145.04 302.4C145.04 302.32 145.04 302.16 145.2 302.16L176.48 292.56L221.12 295.68C221.2 295.68 221.36 295.76 221.36 295.92C221.36 296.08 221.36 296.16 221.2 296.16L189.92 305.76ZM146.56 302.24L189.84 305.28L219.84 296.08L176.48 293.04L146.48 302.24H146.56Z"
fill="#101720"
/>
<path
d="M176.56 293.04L131.92 289.92C131.84 289.92 131.68 289.84 131.68 289.68C131.68 289.6 131.68 289.44 131.84 289.44L163.12 279.84L207.76 282.96C207.84 282.96 208 283.04 208 283.2C208 283.36 208 283.44 207.84 283.44L176.56 293.04ZM133.28 289.52L176.56 292.56L206.56 283.36L163.28 280.32L133.28 289.52Z"
fill="#101720"
/>
<path
d="M189.92 305.76L145.28 302.64C145.2 302.64 145.04 302.56 145.04 302.4C145.04 302.32 145.04 302.16 145.2 302.16L176.48 292.56L221.12 295.68C221.2 295.68 221.36 295.76 221.36 295.92C221.36 296.08 221.36 296.16 221.2 296.16L189.92 305.76ZM146.56 302.24L189.84 305.28L219.84 296.08L176.48 293.04L146.48 302.24H146.56Z"
fill="#101720"
/>
<path
d="M176.56 293.04L131.92 289.92C131.84 289.92 131.68 289.84 131.68 289.68C131.68 289.6 131.68 289.44 131.84 289.44L163.12 279.84L207.76 282.96C207.84 282.96 208 283.04 208 283.2C208 283.36 208 283.44 207.84 283.44L176.56 293.04ZM133.28 289.52L176.56 292.56L206.56 283.36L163.28 280.32L133.28 289.52Z"
fill="#101720"
/>
<path
d="M331.12 206.72C327.52 208.64 323.36 210.56 319.44 212.32C310.88 216.16 303.12 219.12 303.12 219.12L308.8 232.72L244.16 251.36L216.88 252.24L256.16 187.28L149.92 180.24L70.8001 204.16L69.2001 197.44L68.0801 192.8C68.0801 192.8 109.52 178.64 118.8 172.88C128.08 167.12 148.56 145.92 175.28 125.92C202 105.92 224.56 103.84 262.24 122C299.84 140.16 328.64 157.04 339.04 167.68C349.44 178.32 342.64 200.88 331.28 206.88L331.12 206.72Z"
fill="#FFFFFE"
/>
<path
d="M216.8 252.4C216.72 252.4 216.64 252.4 216.56 252.32C216.56 252.32 216.56 252.16 216.56 252.08L255.6 187.44L149.76 180.4L70.6401 204.32H70.4801C70.4801 204.32 70.4001 204.24 70.4001 204.16L67.6801 192.72C67.6801 192.64 67.6801 192.48 67.8401 192.4C68.2401 192.24 109.36 178.16 118.48 172.56C122.64 170 129.04 164.24 137.28 156.96C147.52 147.92 160.24 136.56 174.96 125.6C202.56 104.96 225.36 103.92 262.16 121.68C300.88 140.4 328.96 157.04 339.04 167.44C343.36 171.84 345.12 178.8 343.84 186.56C342.4 195.52 337.36 203.76 331.2 206.96C328 208.64 324 210.56 319.52 212.56C311.84 216 304.8 218.72 303.44 219.28L309.04 232.64V232.8C309.04 232.8 308.96 232.88 308.88 232.96L244.24 251.6L216.88 252.48L216.8 252.4ZM149.84 179.92L256.08 186.96C256.16 186.96 256.24 186.96 256.24 187.12C256.24 187.12 256.24 187.28 256.24 187.36L217.2 252L244.08 251.12L308.4 232.56L302.8 219.28V219.12C302.8 219.12 302.8 219.04 302.96 218.96C302.96 218.96 310.8 215.92 319.28 212.16C323.76 210.16 327.68 208.32 330.96 206.56C336.96 203.44 342 195.36 343.36 186.48C344.56 178.88 342.88 172 338.64 167.76C328.56 157.44 300.56 140.8 261.92 122.16C225.36 104.48 202.64 105.52 175.28 126C160.56 137.04 147.84 148.32 137.6 157.36C129.44 164.64 122.96 170.4 118.8 172.96C109.92 178.48 71.4401 191.68 68.2401 192.8L70.8801 203.76L149.76 179.92H149.84Z"
fill="#101720"
/>
<path
d="M322.64 210.56C335.92 201.76 341.76 190.72 339.2 179.2C336.8 168.64 317.76 154.32 283.92 137.76C255.76 124 235.68 114.88 214.88 114.88C194.08 114.88 208.08 115.12 204.72 115.6C184.88 118.48 166 136.72 150.8 151.36C147.2 154.8 143.76 158.08 140.56 161.04C124.16 175.76 118 179.44 69.2 196.96L68.24 192.8C71.44 191.68 109.92 178.48 118.8 172.96C122.96 170.4 129.44 164.64 137.6 157.36C147.84 148.32 160.48 137.04 175.28 126C190.32 114.72 203.44 109.68 217.76 109.68C232.08 109.68 244.4 113.6 262 122.08C300.72 140.8 328.72 157.36 338.72 167.68C342.88 172 344.64 178.8 343.44 186.4C342 195.28 337.04 203.28 331.04 206.48C328.64 207.76 325.84 209.12 322.64 210.56Z"
fill="#F1EBFE"
/>
<path
d="M207.84 245.76L239.12 252.16H239.2L283.84 244.48L252.48 238.08L207.84 245.76Z"
fill="#FFFFFE"
/>
<path
d="M239.12 252.4L207.84 246C207.76 246 207.68 245.84 207.68 245.76C207.68 245.68 207.76 245.52 207.84 245.52L252.48 237.84C252.48 237.84 252.48 237.84 252.56 237.84L283.84 244.24C283.92 244.24 284 244.4 284 244.48C284 244.56 283.92 244.72 283.84 244.72L239.2 252.4C239.2 252.4 239.2 252.4 239.12 252.4ZM209.12 245.76L239.12 251.92L282.48 244.48L252.48 238.32L209.12 245.76Z"
fill="#101720"
/>
<path
d="M176.56 239.36L207.84 245.76L252.48 238.08L221.2 231.68L176.56 239.36Z"
fill="#FFFFFE"
/>
<path
d="M207.84 246L176.56 239.6C176.48 239.6 176.4 239.44 176.4 239.36C176.4 239.28 176.48 239.12 176.56 239.12L221.2 231.44C221.2 231.44 221.2 231.44 221.28 231.44L252.56 237.84C252.64 237.84 252.72 238 252.72 238.08C252.72 238.16 252.64 238.32 252.56 238.32L207.92 246H207.84ZM177.84 239.36L207.84 245.52L251.2 238.08L221.2 231.92L177.84 239.36Z"
fill="#101720"
/>
<path
d="M100.64 240.64L131.92 247.04L176.56 239.36L145.28 232.96L100.64 240.64Z"
fill="#FFFFFE"
/>
<path
d="M131.92 247.28L100.64 240.88C100.56 240.88 100.48 240.72 100.48 240.64C100.48 240.56 100.56 240.4 100.64 240.4L145.28 232.72C145.28 232.72 145.28 232.72 145.36 232.72L176.64 239.12C176.72 239.12 176.8 239.28 176.8 239.36C176.8 239.44 176.72 239.6 176.64 239.6L132 247.28H131.92ZM101.92 240.64L131.92 246.8L175.2 239.36L145.2 233.2L101.84 240.64H101.92Z"
fill="#101720"
/>
<path
d="M145.28 232.96L176.56 239.36L221.2 231.68L189.92 225.28L145.28 232.96Z"
fill="#FFFFFE"
/>
<path
d="M176.56 239.6L145.2 233.2C145.12 233.2 145.04 233.04 145.04 232.96C145.04 232.88 145.12 232.72 145.2 232.72L189.84 225.04C189.84 225.04 189.84 225.04 189.92 225.04L221.2 231.44C221.28 231.44 221.36 231.6 221.36 231.68C221.36 231.76 221.28 231.92 221.2 231.92L176.56 239.6ZM146.56 232.96L176.56 239.12L219.92 231.68L189.92 225.52L146.56 232.96Z"
fill="#101720"
/>
<path
d="M56 248.32L87.28 254.72L131.92 247.04L100.64 240.64L56 248.32Z"
fill="#FFFFFE"
/>
<path
d="M87.28 254.96L56 248.56C55.92 248.56 55.84 248.4 55.84 248.32C55.84 248.24 55.92 248.08 56 248.08L100.56 240.4C100.56 240.4 100.64 240.4 100.72 240.4L132 246.8C132.08 246.8 132.16 246.96 132.16 247.04C132.16 247.12 132.08 247.28 132 247.28L87.36 254.96H87.28ZM57.28 248.32L87.28 254.48L130.64 247.04L100.64 240.88L57.28 248.32Z"
fill="#101720"
/>
<path
d="M87.28 254.72L118.56 261.12L163.2 253.44L131.92 247.04L87.28 254.72Z"
fill="#FFFFFE"
/>
<path
d="M118.56 261.36L87.28 254.96C87.2 254.96 87.12 254.8 87.12 254.72C87.12 254.64 87.2 254.48 87.28 254.48L131.92 246.8H132L163.28 253.2C163.36 253.2 163.44 253.36 163.44 253.44C163.44 253.52 163.36 253.68 163.28 253.68L118.64 261.36H118.56ZM88.56 254.72L118.56 260.88L161.92 253.44L131.92 247.28L88.56 254.72Z"
fill="#101720"
/>
<path
d="M118.56 261.12V299.28L149.84 305.44V267.52L118.56 261.12Z"
fill="#FF9C0F"
/>
<path
d="M149.84 305.6L118.56 299.44C118.48 299.44 118.4 299.28 118.4 299.2V261.04C118.4 261.04 118.4 260.88 118.48 260.88C118.56 260.88 118.64 260.88 118.64 260.88L149.92 267.28C150 267.28 150.08 267.44 150.08 267.52V305.44C150.08 305.44 150.08 305.6 150 305.6C150 305.6 149.92 305.6 149.84 305.6ZM118.8 299.04L149.6 305.12V267.68L118.8 261.36V299.04Z"
fill="#101720"
/>
<path
d="M87.28 254.72V292.88L118.56 299.28V261.12L87.28 254.72Z"
fill="#FF9C0F"
/>
<path
d="M118.56 299.52L87.28 293.12C87.2 293.12 87.12 292.96 87.12 292.88V254.72C87.12 254.72 87.12 254.56 87.2 254.56C87.28 254.56 87.36 254.56 87.36 254.56L118.64 260.96C118.72 260.96 118.8 261.12 118.8 261.2V299.36C118.8 299.36 118.8 299.52 118.72 299.52C118.72 299.52 118.64 299.52 118.56 299.52ZM87.52 292.64L118.32 298.96V261.28L87.52 254.96V292.64Z"
fill="#101720"
/>
<path
d="M56 248.32V286.4L87.28 292.88V254.72L56 248.32Z"
fill="#FF9C0F"
/>
<path
d="M87.28 293.12L56 286.72C55.92 286.72 55.84 286.56 55.84 286.48V248.32C55.84 248.32 55.84 248.16 55.92 248.16H56.08L87.36 254.56C87.44 254.56 87.52 254.72 87.52 254.8V292.96C87.52 292.96 87.52 293.12 87.44 293.12C87.44 293.12 87.36 293.12 87.28 293.12ZM56.24 286.24L87.04 292.56V254.88L56.24 248.56V286.24Z"
fill="#101720"
/>
<path
d="M239.2 252.16V290.32L283.84 282.64V244.48L239.2 252.16Z"
fill="#F1EBFE"
/>
<path
d="M239.2 290.56C239.2 290.56 239.12 290.56 239.04 290.56C239.04 290.56 238.96 290.48 238.96 290.4V252.24C238.96 252.16 239.04 252 239.12 252L283.76 244.32H283.92C283.92 244.32 284 244.4 284 244.48V282.64C284 282.72 283.92 282.88 283.84 282.88L239.2 290.56ZM239.36 252.4V290.08L283.52 282.48V244.8L239.36 252.4Z"
fill="#101720"
/>
<path
d="M194.48 259.6V297.76L239.2 290.08V251.92H239.12L194.48 259.6Z"
fill="#F1EBFE"
/>
<path
d="M194.48 298C194.48 298 194.4 298 194.32 298C194.32 298 194.24 297.92 194.24 297.84V259.68C194.24 259.6 194.32 259.44 194.4 259.44L239.04 251.76C239.04 251.76 239.12 251.76 239.2 251.76C239.28 251.76 239.36 251.92 239.36 252V290.16C239.36 290.24 239.28 290.4 239.2 290.4L194.56 298.08L194.48 298ZM194.72 259.76V297.44L238.88 289.84V252.16L194.72 259.76Z"
fill="#101720"
/>
<path
d="M149.84 267.28V305.44L194.48 297.76V259.6L149.84 267.28Z"
fill="#F1EBFE"
/>
<path
d="M149.84 305.6C149.84 305.6 149.76 305.6 149.68 305.6C149.68 305.6 149.6 305.52 149.6 305.44V267.28C149.6 267.2 149.68 267.04 149.76 267.04L194.4 259.36H194.56C194.56 259.36 194.64 259.44 194.64 259.52V297.68C194.64 297.76 194.56 297.92 194.48 297.92L149.84 305.6ZM150.08 267.44V305.12L194.24 297.52V259.84L150.08 267.44Z"
fill="#101720"
/>
<path
d="M163.2 253.44L194.48 259.84L239.12 252.16L207.84 245.76L163.2 253.44Z"
fill="#FFFFFE"
/>
<path
d="M194.48 260.08L163.2 253.68C163.12 253.68 163.04 253.52 163.04 253.44C163.04 253.36 163.12 253.2 163.2 253.2L207.84 245.52H207.92L239.2 251.92C239.28 251.92 239.36 252.08 239.36 252.16C239.36 252.24 239.28 252.4 239.2 252.4L194.56 260.08H194.48ZM164.56 253.44L194.56 259.6L237.92 252.16L207.92 246L164.64 253.44H164.56Z"
fill="#101720"
/>
<path
d="M145.28 233.2C145.28 233.2 145.28 233.2 145.2 233.2C145.12 233.2 145.04 232.96 145.12 232.88C145.12 232.8 145.36 232.72 145.44 232.8C145.52 232.8 145.6 233.04 145.52 233.12C145.52 233.2 145.36 233.28 145.28 233.28V233.2Z"
fill="#101720"
/>
<path
d="M194.48 260.08L163.2 253.68C163.12 253.68 163.04 253.52 163.04 253.44C163.04 253.36 163.12 253.2 163.2 253.2L207.84 245.52H207.92L239.2 251.92C239.28 251.92 239.36 252.08 239.36 252.16C239.36 252.24 239.28 252.4 239.2 252.4L194.56 260.08H194.48ZM164.56 253.44L194.56 259.6L237.92 252.16L207.92 246L164.64 253.44H164.56Z"
fill="#101720"
/>
<path
d="M145.28 233.2C145.28 233.2 145.28 233.2 145.2 233.2C145.12 233.2 145.04 232.96 145.12 232.88C145.12 232.8 145.36 232.72 145.44 232.8C145.52 232.8 145.6 233.04 145.52 233.12C145.52 233.2 145.36 233.28 145.28 233.28V233.2Z"
fill="#101720"
/>
<path
d="M118.56 261.12L149.84 267.52L194.48 259.84L163.2 253.44L118.56 261.12Z"
fill="#FFFFFE"
/>
<path
d="M131.92 247.04L163.2 253.44L207.84 245.76L176.56 239.36L131.92 247.04Z"
fill="#FFFFFE"
/>
<path
d="M149.84 267.76L118.56 261.36C118.48 261.36 118.4 261.2 118.4 261.12C118.4 261.04 118.48 260.88 118.56 260.88L163.2 253.2H163.28L194.56 259.6C194.64 259.6 194.72 259.76 194.72 259.84C194.72 259.92 194.64 260.08 194.56 260.08L149.92 267.76H149.84ZM119.84 261.12L149.84 267.28L193.2 259.84L163.2 253.68L119.84 261.12Z"
fill="#101720"
/>
<path
d="M163.2 253.68L131.92 247.28C131.84 247.28 131.76 247.12 131.76 247.04C131.76 246.96 131.84 246.8 131.92 246.8L176.56 239.12L207.92 245.52C208 245.52 208.08 245.68 208.08 245.76C208.08 245.84 208 246 207.92 246L163.28 253.68H163.2ZM133.2 247.04L163.2 253.2L206.48 245.76L176.48 239.6L133.12 247.04H133.2Z"
fill="#101720"
/>
<path
d="M149.84 267.76L118.56 261.36C118.48 261.36 118.4 261.2 118.4 261.12C118.4 261.04 118.48 260.88 118.56 260.88L163.2 253.2H163.28L194.56 259.6C194.64 259.6 194.72 259.76 194.72 259.84C194.72 259.92 194.64 260.08 194.56 260.08L149.92 267.76H149.84ZM119.84 261.12L149.84 267.28L193.2 259.84L163.2 253.68L119.84 261.12Z"
fill="#101720"
/>
<path
d="M163.2 253.68L131.92 247.28C131.84 247.28 131.76 247.12 131.76 247.04C131.76 246.96 131.84 246.8 131.92 246.8L176.56 239.12L207.92 245.52C208 245.52 208.08 245.68 208.08 245.76C208.08 245.84 208 246 207.92 246L163.28 253.68H163.2ZM133.2 247.04L163.2 253.2L206.48 245.76L176.48 239.6L133.12 247.04H133.2Z"
fill="#101720"
/>
<path
d="M131.92 202.08L100.64 211.68L56 208.56L87.28 198.96L131.92 202.08Z"
fill="#FFFFFE"
/>
<path
d="M100.64 211.92L56 208.8C55.92 208.8 55.76 208.72 55.76 208.56C55.76 208.48 55.76 208.32 55.92 208.32L87.2 198.72C87.2 198.72 87.2 198.72 87.28 198.72L131.92 201.84C132 201.84 132.16 201.92 132.16 202.08C132.16 202.16 132.16 202.32 132 202.32L100.72 211.92H100.64ZM57.28 208.4L100.56 211.44L130.56 202.24L87.28 199.2L57.28 208.4Z"
fill="#101720"
/>
<path
d="M163.2 192.48L131.92 202.08L87.2799 198.96L118.56 189.36L163.2 192.48Z"
fill="#FFFFFE"
/>
<path
d="M131.92 202.32L87.2 199.2C87.12 199.2 86.96 199.12 86.96 198.96C86.96 198.88 86.96 198.72 87.12 198.72L118.4 189.12C118.4 189.12 118.4 189.12 118.48 189.12L163.12 192.24C163.2 192.24 163.36 192.32 163.36 192.48C163.36 192.56 163.36 192.72 163.2 192.72L131.92 202.32ZM88.56 198.8L131.92 201.84L161.92 192.64L118.64 189.6L88.64 198.8H88.56Z"
fill="#101720"
/>
<path
d="M239.2 186L207.84 195.6L163.2 192.48L194.48 182.88L239.2 186Z"
fill="#FFFFFE"
/>
<path
d="M207.84 195.84L163.2 192.72C163.12 192.72 162.96 192.64 162.96 192.48C162.96 192.4 162.96 192.24 163.12 192.24L194.4 182.64C194.4 182.64 194.4 182.64 194.48 182.64L239.12 185.76C239.2 185.76 239.36 185.84 239.36 186C239.36 186.16 239.36 186.24 239.2 186.24L207.92 195.84H207.84ZM164.56 192.32L207.84 195.36L237.84 186.16L194.48 183.12L164.48 192.32H164.56Z"
fill="#101720"
/>
<path
d="M194.48 182.88L163.2 192.48L118.56 189.36L149.92 179.76L194.48 182.88Z"
fill="#FFFFFE"
/>
<path
d="M163.2 192.72L118.56 189.6C118.48 189.6 118.32 189.52 118.32 189.36C118.32 189.28 118.32 189.12 118.48 189.12L149.76 179.52C149.76 179.52 149.76 179.52 149.84 179.52L194.48 182.64C194.56 182.64 194.72 182.72 194.72 182.88C194.72 182.96 194.72 183.12 194.56 183.12L163.28 192.72H163.2ZM119.92 189.2L163.2 192.24L193.2 183.04L149.92 180L119.92 189.2Z"
fill="#101720"
/>
<path
d="M283.84 189.12L252.48 198.72L207.84 195.6L239.2 186L283.84 189.12Z"
fill="#FFFFFE"
/>
<path
d="M252.48 198.96L207.84 195.84C207.76 195.84 207.6 195.76 207.6 195.6C207.6 195.44 207.6 195.36 207.76 195.36L239.04 185.76L283.68 188.88C283.76 188.88 283.92 188.96 283.92 189.12C283.92 189.28 283.92 189.36 283.76 189.36L252.48 198.96ZM209.2 195.44L252.48 198.48L282.48 189.28L239.2 186.24L209.2 195.44Z"
fill="#101720"
/>
<path
d="M252.48 198.72L221.2 208.32L176.56 205.2L207.84 195.6L252.48 198.72Z"
fill="#FFFFFE"
/>
<path
d="M221.2 208.56L176.56 205.44C176.48 205.44 176.32 205.36 176.32 205.2C176.32 205.12 176.32 204.96 176.48 204.96L207.76 195.36L252.4 198.48C252.48 198.48 252.64 198.56 252.64 198.72C252.64 198.88 252.64 198.96 252.48 198.96L221.2 208.56ZM177.84 205.04L221.12 208.08L251.12 198.88L207.76 195.84L177.76 205.04H177.84Z"
fill="#101720"
/>
<path
d="M221.2 208.32V246.48L189.92 255.84V217.92L221.2 208.32Z"
fill="#FF9C0F"
/>
<path
d="M189.92 256C189.92 256 189.84 256 189.76 256C189.76 256 189.68 255.92 189.68 255.84V217.92C189.68 217.84 189.68 217.76 189.84 217.68L221.12 208.08C221.12 208.08 221.28 208.08 221.36 208.08C221.36 208.08 221.44 208.16 221.44 208.24V246.4C221.44 246.48 221.44 246.56 221.28 246.64L190 256H189.92ZM190.16 218.08V255.44L220.96 246.24V208.56L190.16 218V218.08Z"
fill="#101720"
/>
<path
d="M252.48 198.72V236.88L221.2 246.48V208.32L252.48 198.72Z"
fill="#FF9C0F"
/>
<path
d="M221.2 246.72C221.2 246.72 221.12 246.72 221.04 246.72C221.04 246.72 220.96 246.64 220.96 246.56V208.4C220.96 208.32 220.96 208.24 221.12 208.16L252.4 198.56C252.4 198.56 252.56 198.56 252.64 198.56C252.64 198.56 252.72 198.64 252.72 198.72V236.88C252.72 236.96 252.72 237.04 252.56 237.12L221.28 246.72H221.2ZM221.44 208.48V246.16L252.24 236.72V199.04L221.44 208.48Z"
fill="#101720"
/>
<path
d="M283.84 189.12V227.28L252.48 236.88V198.72L283.84 189.12Z"
fill="#FF9C0F"
/>
<path
d="M252.48 237.12C252.48 237.12 252.4 237.12 252.32 237.12C252.32 237.12 252.24 237.04 252.24 236.96V198.8C252.24 198.72 252.24 198.64 252.4 198.56L283.68 188.96C283.68 188.96 283.84 188.96 283.92 188.96C283.92 188.96 284 189.04 284 189.12V227.28C284 227.36 284 227.44 283.84 227.52L252.56 237.12H252.48ZM252.72 198.88V236.56L283.52 227.12V189.44L252.72 198.88Z"
fill="#101720"
/>
<path
d="M100.64 211.68V249.84L56 246.72V208.56L100.64 211.68Z"
fill="#F1EBFE"
/>
<path
d="M100.64 250.08L56 246.96C55.84 246.96 55.76 246.88 55.76 246.72V208.56V208.4C55.76 208.4 55.84 208.4 55.92 208.4L100.56 211.52C100.72 211.52 100.8 211.6 100.8 211.76V249.92V250.08C100.8 250.08 100.72 250.08 100.64 250.08ZM56.24 246.48L100.4 249.6V211.92L56.24 208.8V246.48Z"
fill="#101720"
/>
<path
d="M145.28 214.479V252.719L100.64 249.599V211.439L145.28 214.479Z"
fill="#F1EBFE"
/>
<path
d="M145.28 252.88L100.64 249.76C100.48 249.76 100.4 249.68 100.4 249.52V211.36C100.4 211.2 100.48 211.12 100.64 211.12L145.28 214.24C145.44 214.24 145.52 214.32 145.52 214.48V252.64V252.8C145.52 252.8 145.44 252.8 145.36 252.8L145.28 252.88ZM100.88 249.36L145.04 252.48V214.8L100.88 211.76V249.44V249.36Z"
fill="#101720"
/>
<path
d="M189.92 217.6V255.84L145.28 252.72V214.48L189.92 217.6Z"
fill="#F1EBFE"
/>
<path
d="M189.92 256L145.28 252.88C145.12 252.88 145.04 252.8 145.04 252.64V214.48V214.32C145.04 214.32 145.12 214.32 145.2 214.32L189.84 217.44C190 217.44 190.08 217.52 190.08 217.68V255.84V256C190.08 256 190 256 189.92 256ZM145.52 252.48L189.68 255.6V217.92L145.52 214.8V252.48Z"
fill="#101720"
/>
<path
d="M176.56 205.2L145.28 214.8L100.64 211.68L131.92 202.08L176.56 205.2Z"
fill="#FFFFFE"
/>
<path
d="M145.28 215.04L100.64 211.92C100.56 211.92 100.4 211.84 100.4 211.68C100.4 211.6 100.4 211.44 100.56 211.44L131.84 201.84L176.48 204.96C176.56 204.96 176.72 205.04 176.72 205.2C176.72 205.28 176.72 205.44 176.56 205.44L145.28 215.04ZM101.92 211.52L145.2 214.56L175.2 205.36L131.92 202.32L101.92 211.52Z"
fill="#101720"
/>
<path
d="M194.48 183.12C194.4 183.12 194.32 183.12 194.24 182.96C194.24 182.88 194.24 182.72 194.32 182.64C194.4 182.64 194.56 182.64 194.64 182.72C194.64 182.8 194.64 182.96 194.56 183.04C194.56 183.04 194.56 183.04 194.48 183.04V183.12Z"
fill="#101720"
/>
<path
d="M145.28 215.04L100.64 211.92C100.56 211.92 100.4 211.84 100.4 211.68C100.4 211.6 100.4 211.44 100.56 211.44L131.84 201.84L176.48 204.96C176.56 204.96 176.72 205.04 176.72 205.2C176.72 205.28 176.72 205.44 176.56 205.44L145.28 215.04ZM101.92 211.52L145.2 214.56L175.2 205.36L131.92 202.32L101.92 211.52Z"
fill="#101720"
/>
<path
d="M194.48 183.12C194.4 183.12 194.32 183.12 194.24 182.96C194.24 182.88 194.24 182.72 194.32 182.64C194.4 182.64 194.56 182.64 194.64 182.72C194.64 182.8 194.64 182.96 194.56 183.04C194.56 183.04 194.56 183.04 194.48 183.04V183.12Z"
fill="#101720"
/>
<path
d="M221.2 208.32L189.92 217.92L145.28 214.8L176.56 205.2L221.2 208.32Z"
fill="#FFFFFE"
/>
<path
d="M207.84 195.6L176.56 205.2L131.92 202.08L163.2 192.48L207.84 195.6Z"
fill="#FFFFFE"
/>
<path
d="M189.92 218.16L145.28 215.04C145.2 215.04 145.04 214.96 145.04 214.8C145.04 214.72 145.04 214.56 145.2 214.56L176.48 204.96L221.12 208.08C221.2 208.08 221.36 208.16 221.36 208.32C221.36 208.48 221.36 208.56 221.2 208.56L189.92 218.16ZM146.56 214.64L189.84 217.68L219.84 208.48L176.48 205.44L146.48 214.64H146.56Z"
fill="#101720"
/>
<path
d="M176.56 205.44L131.92 202.32C131.84 202.32 131.68 202.24 131.68 202.08C131.68 202 131.68 201.84 131.84 201.84L163.12 192.24L207.76 195.36C207.84 195.36 208 195.44 208 195.6C208 195.76 208 195.84 207.84 195.84L176.56 205.44ZM133.28 201.92L176.56 204.96L206.56 195.76L163.28 192.72L133.28 201.92Z"
fill="#101720"
/>
<path
d="M189.92 218.16L145.28 215.04C145.2 215.04 145.04 214.96 145.04 214.8C145.04 214.72 145.04 214.56 145.2 214.56L176.48 204.96L221.12 208.08C221.2 208.08 221.36 208.16 221.36 208.32C221.36 208.48 221.36 208.56 221.2 208.56L189.92 218.16ZM146.56 214.64L189.84 217.68L219.84 208.48L176.48 205.44L146.48 214.64H146.56Z"
fill="#101720"
/>
<path
d="M176.56 205.44L131.92 202.32C131.84 202.32 131.68 202.24 131.68 202.08C131.68 202 131.68 201.84 131.84 201.84L163.12 192.24L207.76 195.36C207.84 195.36 208 195.44 208 195.6C208 195.76 208 195.84 207.84 195.84L176.56 205.44ZM133.28 201.92L176.56 204.96L206.56 195.76L163.28 192.72L133.28 201.92Z"
fill="#101720"
/>
<path
d="M55.68 208.72V216C55.68 216 59.44 216.72 60.4 219.44C61.36 222.16 58.48 223.52 58.48 223.52C58.48 223.52 60.64 224.4 61.12 226.96C61.6 229.52 58.96 231.52 58.96 231.52C58.96 231.52 62.16 234.88 58.8 239.12C58.8 239.12 61.12 243.12 58 246.24C54.88 249.36 35.28 249.12 39.84 239.92C39.84 239.92 32.8 235.36 38.08 230.32C38.08 230.32 31.76 226.08 35.52 221.04C35.52 221.04 32 217.2 35.36 212.8C38.72 208.4 42.72 204.88 42.72 204.88C42.72 204.88 30.24 201.44 32.16 195.28C34.08 189.12 43.6 191.36 50.56 192.88C57.52 194.4 67.84 192.64 67.84 192.64L70.56 204.08L55.6 208.72H55.68Z"
fill="#F48282"
/>
<mask
id="mask0_910_13921"
style={{ maskType: "luminance" }}
maskUnits="userSpaceOnUse"
x="31"
y="191"
width="40"
height="58"
>
<path
d="M55.68 208.72V216C55.68 216 59.44 216.72 60.4 219.44C61.36 222.16 58.48 223.52 58.48 223.52C58.48 223.52 60.64 224.4 61.12 226.96C61.6 229.52 58.96 231.52 58.96 231.52C58.96 231.52 62.16 234.88 58.8 239.12C58.8 239.12 61.12 243.12 58 246.24C54.88 249.36 35.28 249.12 39.84 239.92C39.84 239.92 32.8 235.36 38.08 230.32C38.08 230.32 31.76 226.08 35.52 221.04C35.52 221.04 32 217.2 35.36 212.8C38.72 208.4 42.72 204.88 42.72 204.88C42.72 204.88 30.24 201.44 32.16 195.28C34.08 189.12 43.6 191.36 50.56 192.88C57.52 194.4 67.84 192.64 67.84 192.64L70.56 204.08L55.6 208.72H55.68Z"
fill="white"
/>
</mask>
<g mask="url(#mask0_910_13921)">
<path
d="M30.8801 193.92C30.8801 198.64 39.4401 200.48 42.8001 200C46.1601 199.52 47.2801 198.88 49.0401 198.24C50.8001 197.6 52.2401 197.76 49.0401 200C45.8401 202.24 42.0801 205.36 40.7201 206.8C39.3601 208.24 30.0801 203.12 30.0801 203.12L30.8001 193.92H30.8801Z"
fill="#236FE7"
/>
<path
d="M60.0001 192.88C66.2401 194.48 67.9201 206.8 67.9201 206.8L75.5201 204.24L70.6401 185.52L60.0001 192.88Z"
fill="#236FE7"
/>
<path
d="M57.36 211.68C54.32 212.24 50.48 208.56 46.56 210.08C42.64 211.6 44.8 215.92 49.12 217.28C53.44 218.64 60.96 218.64 61.6 220.16C62.24 221.68 60 223.12 60 223.12C60 223.12 57.12 224.56 55.52 224.64C53.92 224.72 48.88 226 42.08 224.08C35.28 222.16 33.04 218.96 33.04 218.96L33.6 226.32C33.6 226.32 36.72 224.88 41.84 226.64C46.96 228.4 52.72 228.24 56 227.44C59.28 226.64 61.44 224.64 63.12 226.48C64.8 228.32 61.68 230.64 61.68 230.64L60.16 231.28C60.16 231.28 57.12 232.88 52.64 233.2C48.16 233.52 43.76 232.16 41.44 231.76C39.12 231.36 36.64 229.68 36.64 229.68L34.56 233.92C34.56 233.92 36.32 233.04 41.36 234.32C46.4 235.6 52.56 236.08 56.4 234.96C60.24 233.84 62.16 235.2 62.16 235.2L59.76 238.8C59.76 238.8 56.72 240.56 55.52 240.96C54.32 241.36 51.28 242.4 45.68 241.6C40.08 240.8 37.76 238.64 37.76 238.64V243.52C37.76 243.52 40 242 43.68 243.76C47.36 245.52 55.92 244.16 57.44 243.2C58.96 242.24 60.88 242.48 60.88 242.48L69.12 227.76L63.2 214.64L57.52 211.6L57.36 211.68Z"
fill="#236FE7"
/>
</g>
<path
d="M50.16 248.24C46.8 248.24 43.12 247.6 40.96 246C38.88 244.56 38.4 242.48 39.6 240C38.88 239.52 36.24 237.44 35.92 234.64C35.76 233.12 36.4 231.68 37.76 230.32C36.96 229.76 34.64 227.84 34.24 225.2C34 223.76 34.32 222.4 35.28 221.04C34.64 220.24 32.16 216.64 35.28 212.64C38.08 209.04 41.36 205.92 42.32 205.04C40.64 204.56 34.32 202.4 32.32 198.8C31.68 197.68 31.6 196.48 31.92 195.28C33.84 189.12 42.72 191.04 49.84 192.48L50.64 192.64C57.52 194.08 67.76 192.4 67.84 192.4C68 192.4 68.08 192.4 68.08 192.56L70.8 204C70.8 204.16 70.8 204.24 70.64 204.32L55.84 208.88V215.84C56.64 216 59.68 216.96 60.56 219.36C61.36 221.6 59.68 223.04 58.88 223.52C59.52 223.92 60.88 224.96 61.28 226.96C61.76 229.28 59.84 231.12 59.2 231.6C59.84 232.4 61.84 235.52 58.96 239.12C59.36 239.92 60.88 243.52 58.08 246.4C56.96 247.52 53.6 248.24 50.08 248.24H50.16ZM39.6 191.44C36.16 191.44 33.36 192.4 32.4 195.36C32.08 196.4 32.16 197.52 32.72 198.48C34.88 202.4 42.72 204.56 42.8 204.64C42.88 204.64 42.96 204.72 42.96 204.8C42.96 204.88 42.96 204.96 42.96 205.04C42.96 205.04 38.96 208.56 35.6 212.88C32.4 217.04 35.6 220.64 35.76 220.8C35.76 220.88 35.84 221.04 35.76 221.12C34.8 222.4 34.48 223.68 34.64 225.04C35.12 227.92 38.16 230 38.24 230C38.24 230 38.32 230.08 38.32 230.16C38.32 230.24 38.32 230.32 38.32 230.32C36.96 231.6 36.32 233.04 36.4 234.48C36.64 237.36 40 239.6 40 239.6C40.08 239.6 40.16 239.76 40.08 239.92C38.88 242.24 39.28 244.16 41.2 245.52C45.44 248.56 55.68 248.08 57.84 245.92C60.8 242.96 58.72 239.28 58.64 239.12C58.64 239.04 58.64 238.96 58.64 238.88C61.84 234.88 58.96 231.76 58.88 231.6C58.88 231.6 58.88 231.52 58.88 231.44C58.88 231.44 58.88 231.28 58.96 231.28C58.96 231.28 61.52 229.36 61.04 226.96C60.56 224.56 58.56 223.68 58.56 223.68C58.48 223.68 58.4 223.6 58.4 223.44C58.4 223.28 58.4 223.28 58.56 223.2C58.64 223.2 61.28 221.84 60.4 219.36C59.44 216.88 55.84 216.08 55.84 216.08C55.76 216.08 55.68 215.92 55.68 215.84V208.64C55.68 208.56 55.68 208.4 55.84 208.4L70.56 203.84L67.92 192.88C66.4 193.12 57.12 194.4 50.72 193.04L49.92 192.88C46.64 192.16 42.96 191.44 39.76 191.44H39.6Z"
fill="#101720"
/>
<path
d="M50.24 225.36C44.56 225.36 38.4 223.68 35.44 221.12C35.36 221.04 35.36 220.88 35.44 220.8C35.52 220.72 35.68 220.72 35.76 220.8C40.32 224.64 52.16 226.48 58.48 223.28C58.56 223.28 58.72 223.28 58.8 223.36C58.8 223.44 58.8 223.6 58.72 223.68C56.4 224.88 53.44 225.36 50.32 225.36H50.24Z"
fill="#101720"
/>
<path
d="M55.68 216.24C55.68 216.24 55.68 216.24 55.6 216.24C50.72 214.48 48.08 212.48 48.08 212.48C48 212.4 47.92 212.24 48.08 212.16C48.08 212.08 48.32 212 48.4 212.16C48.4 212.16 51.0401 214.16 55.8401 215.84C56.0001 215.84 56 216 56 216.16C56 216.24 55.84 216.32 55.76 216.32L55.68 216.24Z"
fill="#101720"
/>
<path
d="M42.8 205.12C42.8 205.12 42.64 205.12 42.64 205.04C42.56 204.96 42.64 204.8 42.64 204.72C47.36 200.64 50.16 199.04 50.16 199.04C50.24 199.04 50.4 199.04 50.48 199.12C50.48 199.2 50.48 199.36 50.4 199.44C50.4 199.44 47.6 200.96 42.96 205.04C42.96 205.04 42.88 205.04 42.8 205.04V205.12Z"
fill="#101720"
/>
<path
d="M51.04 233.36C46.16 233.36 40.8 232.24 38 230.4C37.92 230.4 37.84 230.16 38 230.08C38 230 38.24 229.92 38.32 230.08C43.76 233.52 55.04 233.76 58.96 231.36C59.04 231.36 59.2 231.36 59.28 231.36C59.28 231.44 59.28 231.6 59.28 231.68C57.44 232.8 54.4 233.36 51.2 233.36H51.04Z"
fill="#101720"
/>
<path
d="M49.6 242.24C46.56 242.24 43.2 241.52 39.76 240.16C39.6 240.16 39.6 240 39.6 239.84C39.6 239.68 39.76 239.68 39.92 239.68C47.2 242.64 54.16 242.4 58.56 238.88C58.64 238.8 58.8 238.88 58.88 238.88C58.96 238.96 58.88 239.12 58.88 239.2C56.4 241.12 53.2 242.08 49.52 242.08L49.6 242.24Z"
fill="#101720"
/>
<path
d="M256.08 187.2C247.28 189.92 238.8 187.2 235.36 189.92C231.92 192.64 241.28 198 241.28 198C241.28 198 225.36 204.32 219.36 208C213.36 211.68 216.96 219.2 224.48 216.4C224.48 216.4 220.16 219.36 222.88 223.12C225.6 226.88 230.96 224.4 230.96 224.4C230.96 224.4 228.72 232.96 236.56 232.72C236.56 232.72 236.32 238 243.68 237.36C251.04 236.72 273.52 230.16 273.52 230.16L256 187.2H256.08Z"
fill="#F48282"
/>
<mask
id="mask1_910_13921"
style={{ maskType: "luminance" }}
maskUnits="userSpaceOnUse"
x="216"
y="187"
width="58"
height="51"
>
<path
d="M256.08 187.2C247.28 189.92 238.8 187.2 235.36 189.92C231.92 192.64 241.28 198 241.28 198C241.28 198 225.36 204.32 219.36 207.92C213.36 211.52 216.96 219.12 224.48 216.32C224.48 216.32 220.16 219.28 222.88 223.04C225.6 226.8 230.96 224.32 230.96 224.32C230.96 224.32 228.72 232.88 236.56 232.64C236.56 232.64 236.32 237.92 243.68 237.28C251.04 236.64 273.52 230.08 273.52 230.08L256 187.12L256.08 187.2Z"
fill="white"
/>
</mask>
<g mask="url(#mask1_910_13921)">
<path
d="M234.72 188.159C234.8 191.999 240.08 194.079 245.28 194.159C250.48 194.239 247.84 195.359 245.68 196.559C243.52 197.759 233.44 200.239 233.44 200.239C233.44 200.239 215.36 206.879 214.08 209.839C212.8 212.799 216.8 215.199 222.4 213.039C228 210.879 234.56 207.759 237.12 207.599C239.68 207.439 241.04 209.599 236.24 211.519C231.44 213.439 219.2 218.079 219.2 218.079C219.2 218.079 220.8 223.279 225.36 222.239C229.92 221.199 238.88 218.479 242.64 217.439C246.4 216.399 250 217.999 244.4 219.839C238.8 221.679 224.64 226.879 224.64 226.879C224.64 226.879 228.72 230.879 233.44 229.999C238.16 229.119 246 226.159 249.04 225.599C252.08 225.039 253.36 226.559 250.24 227.999C247.12 229.439 232.4 234.319 232.4 234.319C232.4 234.319 237.44 237.119 244.24 235.839C251.04 234.479 265.2 231.039 267.6 228.719C270 226.399 270.48 219.279 270.48 219.279L276.64 228.239L275.28 235.439L250.56 239.919L222.16 240.399L209.04 223.439L205.44 197.759L214.32 188.079L234.48 187.919L234.72 188.159Z"
fill="#236FE7"
/>
</g>
<path
d="M242.56 237.6C240.48 237.6 238.88 237.04 237.84 236.08C236.64 234.96 236.4 233.52 236.4 232.96C236.4 232.96 236.4 232.96 236.32 232.96C234.24 232.96 232.72 232.32 231.76 231.12C230.08 229.04 230.48 226 230.72 224.8C229.36 225.28 225.12 226.48 222.8 223.2C222 222.08 221.76 220.96 221.92 219.84C222.16 218.56 222.88 217.6 223.52 216.96C220 217.84 217.6 216.48 216.64 214.56C215.68 212.64 216.16 209.68 219.36 207.84C224.72 204.64 238.16 199.12 240.8 198.08C239.36 197.2 234.64 194.16 234.4 191.6C234.4 190.88 234.64 190.32 235.2 189.84C236.96 188.4 239.92 188.4 243.68 188.4C247.36 188.4 251.6 188.4 256 187.04C256.08 187.04 256.16 187.04 256.24 187.2L273.76 230.16V230.32C273.76 230.32 273.68 230.4 273.6 230.48C273.36 230.48 251.04 237.04 243.76 237.68C243.36 237.68 242.96 237.68 242.56 237.68V237.6ZM236.64 232.4H236.8C236.8 232.4 236.8 232.48 236.8 232.56C236.8 232.56 236.8 234.32 238.08 235.6C239.28 236.72 241.12 237.2 243.68 236.96C250.48 236.4 270.72 230.56 273.2 229.84L255.92 187.36C251.52 188.72 247.2 188.64 243.68 188.64C240 188.64 237.12 188.64 235.52 189.92C235.04 190.32 234.8 190.72 234.88 191.28C235.12 193.92 241.36 197.6 241.44 197.6C241.44 197.6 241.6 197.76 241.52 197.84C241.52 197.92 241.52 198 241.36 198.08C241.2 198.08 225.44 204.48 219.52 208C216.56 209.76 216.16 212.32 217.04 214.16C218 216.08 220.64 217.44 224.48 216C224.56 216 224.72 216 224.8 216.08C224.88 216.16 224.8 216.32 224.8 216.4C224.8 216.4 222.8 217.76 222.48 219.76C222.32 220.8 222.56 221.76 223.28 222.8C225.84 226.4 230.96 224.08 231.04 224.08C231.12 224.08 231.2 224.08 231.28 224.08C231.28 224.08 231.36 224.24 231.28 224.32C231.28 224.32 230.24 228.32 232.16 230.64C233.12 231.84 234.64 232.4 236.72 232.32L236.64 232.4Z"
fill="#101720"
/>
<path
d="M224.56 216.56C224.48 216.56 224.4 216.56 224.32 216.4C224.32 216.24 224.32 216.16 224.48 216.08L238.88 210.24C239.04 210.24 239.12 210.24 239.2 210.4C239.2 210.56 239.2 210.64 239.04 210.72L224.64 216.56C224.64 216.56 224.64 216.56 224.56 216.56Z"
fill="#101720"
/>
<path
d="M231.04 224.64C230.96 224.64 230.88 224.64 230.8 224.48C230.8 224.32 230.8 224.24 230.96 224.16L246.88 218.88C247.04 218.88 247.12 218.88 247.2 219.04C247.2 219.2 247.2 219.28 247.04 219.36L231.12 224.64H231.04Z"
fill="#101720"
/>
<path
d="M236.64 232.88C236.56 232.88 236.48 232.88 236.4 232.72C236.4 232.56 236.4 232.48 236.56 232.4L252.32 227.2C252.48 227.2 252.56 227.2 252.64 227.36C252.64 227.52 252.64 227.6 252.48 227.68L236.72 232.88H236.64Z"
fill="#101720"
/>
<path
d="M241.36 198.24C241.28 198.24 241.2 198.24 241.12 198.08C241.12 197.92 241.12 197.84 241.28 197.76L250.48 194C250.64 194 250.72 194 250.8 194.16C250.8 194.32 250.8 194.4 250.64 194.48L241.44 198.24C241.44 198.24 241.44 198.24 241.36 198.24Z"
fill="#101720"
/>
<path
d="M160.08 181.04C160 181.04 159.84 180.96 159.84 180.8C159.84 180.72 158.32 171.04 156.64 158.72C156.64 158.56 156.64 158.48 156.88 158.48C157.04 158.48 157.12 158.48 157.12 158.72C158.72 171.04 160.24 180.72 160.32 180.8C160.32 180.96 160.32 181.04 160.16 181.04H160.08Z"
fill="#101720"
/>
<path
d="M163.92 116.88C166.16 119.92 172.8 120.8 178 118.64C178 118.64 189.92 121.68 200.24 114.48C200.24 114.48 211.04 118.88 216.96 114.96C216.96 114.96 229.44 116.56 230.24 109.6C230.24 109.6 236 107.2 234.32 101.92C232.56 96.6396 228.16 94.8796 228.16 94.8796C227.84 94.2396 222.96 84.3996 217.12 83.6796C217.12 83.6796 213.36 75.3596 206.32 75.7596C206.32 75.7596 186.96 59.3596 177.92 75.4396C177.92 75.4396 171.28 82.4796 170.64 90.3196C170.64 90.3196 165.52 95.7596 166 102C166 102 161.76 104.4 162.96 109.68C162.96 109.68 161.76 113.92 163.92 116.96V116.88Z"
fill="#FF9C0F"
/>
<path
d="M171.92 120.08C168.48 120.08 165.2 119.04 163.76 117.04C161.6 114.08 162.56 110.16 162.72 109.6C161.68 104.8 165.04 102.32 165.76 101.84C165.36 95.9199 169.84 90.7999 170.4 90.1599C171.12 82.3999 177.68 75.3599 177.76 75.2799C179.92 71.3599 182.96 69.0399 186.72 68.3199C195.44 66.7199 205.44 74.7199 206.4 75.5199C212.96 75.1999 216.8 82.4799 217.28 83.5199C222.96 84.3199 227.76 93.5199 228.32 94.7999C228.96 95.1199 232.88 97.0399 234.48 102C236.08 106.96 231.28 109.52 230.4 109.92C230.24 111.36 229.52 112.48 228.4 113.44C224.8 116.24 217.92 115.52 216.96 115.44C211.2 119.12 201.44 115.44 200.24 114.96C190.4 121.76 179.04 119.36 178 119.12C176.08 119.92 173.92 120.32 171.92 120.32V120.08ZM164.08 116.72C166.24 119.68 172.88 120.56 177.92 118.4C177.92 118.4 178 118.4 178.08 118.4C178.16 118.4 190.08 121.36 200.16 114.32C200.16 114.32 200.32 114.32 200.4 114.32C200.48 114.32 211.12 118.64 216.88 114.8C216.88 114.8 216.96 114.8 217.04 114.8C217.04 114.8 224.56 115.76 228.16 112.96C229.2 112.08 229.84 111.04 230 109.68C230 109.6 230 109.52 230.16 109.52C230.4 109.44 235.68 107.2 234.08 102.16C232.4 97.0399 228.16 95.2799 228.08 95.1999C228.08 95.1999 228 95.1999 227.92 95.0399C227.36 93.9999 222.64 84.6399 217.04 83.9999C216.96 83.9999 216.88 83.9999 216.88 83.8399C216.88 83.7599 213.28 75.9999 206.8 75.9999C200.32 75.9999 206.48 75.9999 206.32 75.9999H206.16C206.08 75.9199 195.68 67.2799 186.8 68.8799C183.2 69.5199 180.24 71.8399 178.16 75.5999C178.08 75.6799 171.52 82.7199 170.88 90.3199C170.88 90.3199 170.88 90.3999 170.88 90.4799C170.88 90.4799 165.84 95.9199 166.32 102C166.32 102.08 166.32 102.16 166.16 102.24C166 102.32 162.16 104.56 163.2 109.6C163.2 109.6 163.2 109.6 163.2 109.68C163.2 109.68 162 113.84 164.16 116.72H164.08Z"
fill="#101720"
/>
<path
d="M163.92 116.88C166.16 119.92 172.8 120.8 178 118.64C178 118.64 189.92 121.68 200.24 114.48C200.24 114.48 211.04 118.88 216.96 114.96C216.96 114.96 229.44 116.56 230.24 109.6C230.24 109.6 236 107.2 234.32 101.92C232.56 96.6399 228.16 94.8799 228.16 94.8799C230.56 101.12 220.96 109.84 215.12 109.04C209.36 108.24 201.68 106.72 201.68 106.72L183.84 110.88C183.84 110.88 180.96 113.76 177.04 113.12C173.04 112.56 166.24 108 166 101.92C166 101.92 161.76 104.32 162.96 109.6C162.96 109.6 161.76 113.84 163.92 116.88Z"
fill="#101720"
/>
<path
d="M171.92 120.08C168.4 120.08 165.2 118.96 163.76 117.04C161.6 114.08 162.56 110.16 162.72 109.6C161.6 104.24 165.84 101.76 165.92 101.76C165.92 101.76 166.08 101.76 166.16 101.76C166.16 101.76 166.24 101.84 166.32 102C166.56 107.68 172.96 112.4 177.12 112.96C180.96 113.52 183.76 110.8 183.76 110.8C183.76 110.8 183.76 110.8 183.84 110.8L201.68 106.64C201.68 106.64 201.68 106.64 201.76 106.64C201.76 106.64 209.52 108.16 215.2 108.96C218.32 109.36 222.88 106.88 225.84 103.2C228.08 100.4 228.8 97.4398 227.92 95.1198C227.92 95.0398 227.92 94.9598 227.92 94.8798C227.92 94.8798 228.08 94.7998 228.16 94.8798C228.32 94.8798 232.72 96.7998 234.4 102.08C236 107.04 231.2 109.6 230.32 110C230.16 111.44 229.44 112.56 228.32 113.52C224.72 116.32 217.84 115.6 216.88 115.52C211.12 119.2 201.36 115.52 200.16 115.04C190.32 121.84 178.96 119.44 177.92 119.2C176 120 173.84 120.4 171.84 120.4L171.92 120.08ZM165.76 102.4C164.8 103.04 162.24 105.36 163.12 109.6C163.12 109.6 163.12 109.6 163.12 109.68C163.12 109.68 161.92 113.84 164.08 116.72C166.24 119.68 172.88 120.56 177.92 118.4C177.92 118.4 178 118.4 178.08 118.4C178.16 118.4 190.08 121.36 200.16 114.32C200.16 114.32 200.32 114.32 200.4 114.32C200.48 114.32 211.12 118.64 216.88 114.8C216.88 114.8 216.96 114.8 217.04 114.8C217.04 114.8 224.56 115.76 228.16 112.96C229.2 112.08 229.84 111.04 230 109.68C230 109.6 230 109.52 230.16 109.52C230.4 109.44 235.68 107.2 234.08 102.16C232.72 98.0798 229.76 96.0798 228.56 95.4398C229.2 97.7598 228.4 100.64 226.16 103.44C223.12 107.28 218.32 109.84 215.04 109.44C209.52 108.72 202.32 107.28 201.6 107.12L183.84 111.28C183.44 111.68 180.64 114.08 176.88 113.6C174.72 113.28 171.92 111.84 169.84 110C167.36 107.84 165.92 105.2 165.68 102.56L165.76 102.4Z"
fill="#101720"
/>
<path
d="M204.72 98.3197C204.24 98.0797 203.92 97.9197 203.92 97.9197L204.08 97.6797C204.08 97.6797 204.4 97.8397 204.8 98.0797V98.3197H204.72Z"
fill="#5C2F00"
/>
<path
d="M205.28 127.2C203.44 128.4 201.52 128.96 200 128.32C195.36 126.48 195.84 121.28 195.84 121.28L194.4 110.88L202.48 101.92L203.68 100.56L210.64 114.56C212.24 119.36 208.96 124.72 205.28 127.2Z"
fill="#F69999"
/>
<path
d="M205.28 127.2C203.44 128.4 201.52 128.96 200 128.32C195.36 126.48 195.84 121.28 195.84 121.28L194.4 110.88L202.48 101.92L203.84 102.56C203.84 102.56 202.56 109.68 200.24 114.56C198.48 118.32 202.48 124.24 205.28 127.28V127.2Z"
fill="#2973E8"
/>
<path
d="M205.92 104.88C205.92 104.88 201.44 112.56 194.88 114.24L194.4 110.88L204.16 101.44L205.84 104.88H205.92Z"
fill="#101720"
/>
<path
d="M194.72 114.56L194.16 110.8L204.24 101.04L206.16 104.88C206.16 105.04 201.6 112.72 195.04 114.48H194.8L194.72 114.56ZM194.64 110.96L195.04 113.92C200.88 112.24 205.04 105.76 205.6 104.88L204.08 101.84L194.64 110.96Z"
fill="#101720"
/>
<path
d="M201.44 128.88C200.88 128.88 200.4 128.8 200 128.64C195.2 126.8 195.68 121.44 195.68 121.36L194.24 110.96V110.8L203.6 100.48C203.6 100.48 203.76 100.4 203.84 100.48C203.84 100.48 204 100.48 204 100.64L210.96 114.64C212.56 119.44 209.44 124.96 205.52 127.6C204.08 128.56 202.72 129.04 201.52 129.04L201.44 128.88ZM194.64 110.96L196.08 121.28C196.08 121.52 195.68 126.4 200.08 128.16C201.44 128.72 203.28 128.32 205.12 127.04C208.88 124.48 211.92 119.2 210.4 114.64L203.6 100.96L194.56 110.96H194.64Z"
fill="#101720"
/>
<path
d="M180.08 109.2C180.64 110.32 181.28 111.2 182 112C186.8 117.68 193.6 115.84 199.44 110.08C202.72 106.88 204.4 102.64 204.88 98.2397C206.4 99.0397 209.84 100.16 210.16 95.4397C210.48 90.2397 206.4 86.7997 204.24 89.9997C204.24 90.0797 204.08 90.2397 204 90.3197C203.6 91.4397 203.36 92.6397 203.28 93.8397C203.28 94.1597 203.28 94.4797 203.12 94.7997C202.88 95.3597 202.32 95.7597 201.68 95.7597C201.6 94.9597 201.52 94.1597 201.44 93.3597C201.28 92.2397 201.2 91.1197 200.88 90.0797C198.8 90.2397 196.8 89.8397 194.8 89.1197C192.24 88.2397 190 86.7197 187.84 85.1197C187.84 85.1197 187.68 85.1197 187.6 85.1997C181.52 87.8397 179.28 84.2397 179.28 84.2397L178.56 86.4797C177.28 90.7197 176.88 95.1197 177.28 99.4397C177.6 102.56 178.4 106 180.08 109.2Z"
fill="#F69999"
/>
<path
d="M189.44 96.7998C189.44 96.7998 190.4 94.3198 193.44 94.3198C196.48 94.3198 197.12 96.2398 197.12 96.2398C197.12 96.2398 196.16 98.7998 193.44 98.8798C190.72 98.8798 189.44 96.8798 189.44 96.8798V96.7998Z"
fill="#FFFFFE"
/>
<mask
id="mask2_910_13921"
style={{ maskType: "luminance" }}
maskUnits="userSpaceOnUse"
x="189"
y="94"
width="9"
height="5"
>
<path
d="M189.44 96.7998C189.44 96.7998 190.4 94.3198 193.44 94.3198C196.48 94.3198 197.12 96.2398 197.12 96.2398C197.12 96.2398 196.16 98.7998 193.44 98.8798C190.72 98.8798 189.44 96.8798 189.44 96.8798V96.7998Z"
fill="white"
/>
</mask>
<g mask="url(#mask2_910_13921)">
<path
d="M192.16 99.0397C193.22 99.0397 194.08 98.1801 194.08 97.1197C194.08 96.0593 193.22 95.1997 192.16 95.1997C191.1 95.1997 190.24 96.0593 190.24 97.1197C190.24 98.1801 191.1 99.0397 192.16 99.0397Z"
fill="#101720"
/>
</g>
<path
d="M185.76 104.32C184.96 104.32 184.32 103.84 184 103.2C183.68 102.48 183.68 101.68 184 101.12C184.56 100.24 185.44 98.16 185.2 95.76C185.2 95.6 185.28 95.52 185.44 95.52C185.6 95.52 185.68 95.6 185.68 95.76C186 98.32 185.04 100.56 184.4 101.44C184.08 101.92 184.08 102.56 184.4 103.04C184.56 103.36 184.96 103.84 185.76 103.92C185.92 103.92 186 104.08 186 104.16C186 104.32 185.92 104.4 185.76 104.4V104.32Z"
fill="#101720"
/>
<path
d="M191.36 105.84C191.04 105.84 190.8 105.84 190.48 105.68C190.32 105.68 190.32 105.52 190.32 105.36C190.32 105.2 190.48 105.2 190.64 105.2C191.28 105.44 191.84 105.36 192.32 105.04C192.8 104.64 193.04 103.92 192.88 103.12C192.88 102.96 192.88 102.88 193.04 102.8C193.2 102.8 193.28 102.8 193.36 102.96C193.6 104 193.36 104.88 192.64 105.36C192.32 105.68 191.84 105.84 191.36 105.84Z"
fill="#101720"
/>
<path
d="M189.6 93.9198C189.6 93.9198 189.52 93.9198 189.44 93.9198C189.36 93.8398 189.28 93.6798 189.44 93.5998C190.24 92.5598 191.68 91.9198 193.28 91.8398C194.72 91.8398 196.08 92.2398 196.8 93.0398C196.88 93.1198 196.88 93.2798 196.8 93.3598C196.72 93.4398 196.56 93.4398 196.48 93.3598C195.84 92.6398 194.64 92.2398 193.28 92.3198C191.84 92.3198 190.56 92.9598 189.84 93.8398C189.84 93.8398 189.76 93.9198 189.68 93.9198H189.6Z"
fill="#101720"
/>
<path
d="M184.8 93.7601C184.8 93.7601 184.72 93.7601 184.64 93.7601C184.56 93.7601 182.24 92.0001 180.4 93.6001C180.32 93.6801 180.16 93.6001 180.08 93.6001C180 93.5201 180.08 93.3601 180.08 93.2801C182.24 91.3601 184.96 93.3601 184.96 93.4401C185.04 93.5201 185.12 93.6801 184.96 93.7601C184.96 93.7601 184.88 93.8401 184.8 93.8401V93.7601Z"
fill="#101720"
/>
<path
d="M193.44 94.32C193.44 94.32 194.88 94.24 196 94.96C197.12 95.68 197.6 96.4 197.92 96.48L197.52 97.04C197.52 97.04 195.52 94.56 193.44 94.4V94.32Z"
fill="#101720"
/>
<path
d="M185.2 96.8801C185.2 96.8801 184.16 94.8801 181.6 95.1201C179.04 95.3601 178.64 97.0401 178.64 97.0401C178.64 97.0401 179.68 99.1201 182 98.9601C184.32 98.8001 185.2 96.9601 185.2 96.9601V96.8801Z"
fill="#FFFFFE"
/>
<mask
id="mask3_910_13921"
style={{ maskType: "luminance" }}
maskUnits="userSpaceOnUse"
x="178"
y="95"
width="8"
height="4"
>
<path
d="M185.2 96.8801C185.2 96.8801 184.16 94.8801 181.6 95.1201C179.04 95.3601 178.64 97.0401 178.64 97.0401C178.64 97.0401 179.68 99.1201 182 98.9601C184.32 98.8001 185.2 96.9601 185.2 96.9601V96.8801Z"
fill="white"
/>
</mask>
<g mask="url(#mask3_910_13921)">
<path
d="M182 98.9601C182.928 98.9601 183.68 98.2079 183.68 97.2801C183.68 96.3523 182.928 95.6001 182 95.6001C181.072 95.6001 180.32 96.3523 180.32 97.2801C180.32 98.2079 181.072 98.9601 182 98.9601Z"
fill="#101720"
/>
</g>
<path
d="M181.6 95.04C181.6 95.04 180.4 95.04 179.52 95.76C178.64 96.48 178.32 97.12 178 97.2L178.4 97.6C178.4 97.6 179.92 95.36 181.68 95.04H181.6Z"
fill="#101720"
/>
<path
d="M204.88 95.2799C204.64 95.2799 204.56 95.0399 204.56 94.8799C204.96 92.7999 205.36 91.7599 206.08 91.3599C206.48 91.1199 206.88 91.0399 207.44 91.1999C207.68 91.1999 207.76 91.4399 207.68 91.6799C207.68 91.9199 207.44 91.9999 207.2 91.9199C206.88 91.9199 206.64 91.9199 206.48 91.9199C206 92.2399 205.6 93.1999 205.28 94.9599C205.28 95.1199 205.12 95.2799 204.88 95.2799Z"
fill="#101720"
/>
<path
d="M181.92 112C186.72 117.68 193.52 115.84 199.36 110.08C202.64 106.88 204.32 102.64 204.8 98.2396C206.32 99.0396 209.76 100.16 210.08 95.4396C210.4 90.2396 206.32 86.7996 204.16 89.9996C204.16 90.0796 204 90.2396 203.92 90.3196C203.52 91.4396 203.28 92.6396 203.2 93.8396C203.2 94.1596 203.2 94.4796 203.04 94.7996C202.8 95.3596 202.24 95.7596 201.6 95.7596C201.52 94.9596 201.44 94.1596 201.36 93.3596C201.2 92.2396 201.12 91.1196 200.8 90.0796C198.72 90.2396 196.72 89.8396 194.72 89.1196C192.16 88.2396 189.92 86.7196 187.76 85.1196C187.76 85.1196 187.6 85.1196 187.52 85.1996C191.2 89.9196 200 91.4396 198.32 100.8C196.08 113.84 186.56 112.08 181.92 112Z"
fill="#2973E8"
/>
<path
d="M204.8 94.3996C204.64 94.3996 204.56 94.2396 204.64 94.1596C204.64 93.9996 205.28 90.6396 207.28 90.6396C207.44 90.6396 207.52 90.7196 207.52 90.8796C207.52 91.0396 207.44 91.1196 207.28 91.1196C205.68 91.1196 205.12 94.2396 205.12 94.2396C205.12 94.3196 204.96 94.4796 204.88 94.4796L204.8 94.3996Z"
fill="#101720"
/>
<path
d="M207.2 96.3997C207.2 96.3997 207.12 96.3997 207.04 96.3997C206.96 96.3197 206.96 96.1597 207.04 96.0797C207.76 95.2797 207.68 93.7597 207.2 92.7197C206.88 92.0797 206.48 91.6797 206.08 91.6797C205.92 91.6797 205.84 91.5997 205.84 91.4397C205.84 91.2797 205.92 91.1997 206.08 91.1997C206.64 91.1997 207.2 91.6797 207.6 92.5597C208.16 93.7597 208.24 95.4397 207.36 96.3997C207.36 96.3997 207.28 96.3997 207.2 96.3997Z"
fill="#101720"
/>
<path
d="M179.2 84.4C179.2 84.4 179.12 84.4 179.04 84.4C177.36 82.88 177.36 81.28 177.36 81.2C177.36 81.04 177.44 80.96 177.6 80.96C177.76 80.96 177.84 81.04 177.84 81.2C177.84 81.2 177.84 82.64 179.36 84C179.44 84.08 179.44 84.24 179.36 84.32C179.36 84.32 179.28 84.32 179.2 84.32V84.4Z"
fill="#101720"
/>
<path
d="M188.8 115.68C188.64 115.68 188.56 115.68 188.4 115.68C185.84 115.6 183.6 114.4 181.76 112.16C181.12 111.36 180.48 110.4 179.84 109.36C178.32 106.56 177.36 103.2 176.96 99.52C176.56 95.2 176.96 90.8 178.24 86.4L178.96 84.16C178.96 84.08 179.04 84 179.12 84C179.2 84 179.28 84 179.36 84.08C179.44 84.24 181.6 87.44 187.36 84.96C187.36 84.96 187.44 84.96 187.52 84.96C187.6 84.96 187.76 84.96 187.84 84.96C190.24 86.88 192.48 88.16 194.72 88.96C196.72 89.68 198.8 90 200.64 89.84C200.8 89.84 200.88 89.84 200.88 90C201.2 91.12 201.28 92.24 201.44 93.28V93.68C201.52 94.32 201.6 94.88 201.68 95.52C202.08 95.52 202.48 95.12 202.64 94.72C202.72 94.48 202.8 94.16 202.8 93.84C202.88 92.64 203.12 91.44 203.52 90.24C203.6 90.08 203.68 89.92 203.76 89.84C204.56 88.72 205.68 88.24 206.8 88.64C208.56 89.28 210.32 91.84 210.08 95.44C210 97.12 209.44 98.32 208.56 98.88C207.36 99.6 205.84 99.12 204.8 98.64C204.32 103.28 202.4 107.28 199.36 110.32C195.76 113.84 192 115.76 188.64 115.76L188.8 115.68ZM180.24 109.04C180.8 110.08 181.44 111.04 182.08 111.76C183.84 113.84 186 114.96 188.4 115.12C191.76 115.28 195.52 113.36 199.2 109.84C202.24 106.88 204.08 102.8 204.56 98.16C204.56 98.16 204.56 98 204.72 98C204.72 98 204.88 98 204.96 98C205.84 98.4 207.44 99.04 208.56 98.4C209.36 97.92 209.76 96.96 209.84 95.36C210 92.16 208.48 89.6 206.88 89.04C205.92 88.72 205.04 89.04 204.32 90.08C204.32 90.16 204.16 90.32 204.08 90.4C203.76 91.52 203.52 92.64 203.44 93.84C203.44 94.16 203.44 94.56 203.28 94.88C203.04 95.52 202.32 96 201.6 96C201.52 96 201.36 95.92 201.36 95.76C201.28 95.04 201.2 94.4 201.12 93.68V93.28C200.96 92.24 200.8 91.2 200.56 90.16C198.64 90.24 196.56 89.92 194.64 89.2C192.4 88.4 190.16 87.12 187.76 85.2C187.76 85.2 187.76 85.2 187.68 85.2C182.72 87.36 180.16 85.36 179.36 84.48L178.8 86.32C177.52 90.56 177.12 94.96 177.52 99.2C177.92 102.88 178.8 106.08 180.32 108.8L180.24 109.04Z"
fill="#101720"
/>
<path
d="M208.88 79.5998C208.8 79.5998 208.64 79.5998 208.64 79.4398C208.64 79.4398 208.08 77.5198 206.16 75.9998C206.08 75.9198 206 75.7598 206.16 75.6798C206.24 75.5998 206.4 75.5198 206.48 75.6798C208.56 77.2798 209.12 79.2798 209.12 79.3598C209.12 79.5198 209.12 79.5998 208.96 79.6798L208.88 79.5998Z"
fill="#101720"
/>
<path
d="M280.32 179.28L275.28 180.96C275.28 180.96 262.64 173.04 255.28 166C257.52 167.6 260 169.12 262.56 170.56C272.8 176.32 280.32 179.36 280.32 179.36V179.28Z"
fill="#101720"
/>
<path
d="M275.28 181.12C275.28 181.12 275.2 181.12 275.12 181.12C274.96 181.12 262.4 173.12 255.12 166.16C255.04 166.08 255.04 165.92 255.12 165.84C255.2 165.76 255.36 165.76 255.44 165.84C257.84 167.6 260.4 169.12 262.64 170.32C272.8 176 280.32 179.04 280.32 179.04C280.4 179.04 280.48 179.2 280.48 179.28C280.48 179.36 280.48 179.44 280.32 179.52L275.28 181.12ZM258.08 168.08C265.04 174 274.32 179.92 275.36 180.64L279.68 179.2C277.68 178.4 271.04 175.44 262.48 170.64C261.12 169.84 259.6 168.96 258.08 168V168.08Z"
fill="#101720"
/>
<path
d="M255.36 166.24C255.36 166.24 255.28 166.24 255.2 166.24C249.52 162.08 243.36 155.68 246.48 143.2C246.48 143.04 246.64 142.96 246.8 143.04C246.96 143.04 247.04 143.2 246.96 143.36C243.92 155.6 249.92 161.84 255.52 165.84C255.6 165.84 255.68 166.08 255.52 166.16C255.36 166.24 255.44 166.24 255.36 166.24Z"
fill="#101720"
/>
<path
d="M255.36 166.24C255.36 166.24 255.28 166.24 255.2 166.24C255.2 166.24 255.2 166.16 255.2 166.08C255.2 166 255.2 165.92 255.2 165.92C255.28 165.84 255.44 165.84 255.52 165.92C255.6 166 255.52 166 255.52 166.08C255.52 166.16 255.52 166.24 255.52 166.24C255.52 166.24 255.44 166.24 255.36 166.24Z"
fill="#101720"
/>
<path
d="M305.04 223.84L273.52 230.16C288.8 225.28 303.04 219.12 303.04 219.12L305.04 223.84Z"
fill="#101720"
/>
<path
d="M273.6 230.4C273.52 230.4 273.36 230.4 273.36 230.24C273.36 230.08 273.36 230 273.52 229.92C288.64 225.04 302.88 218.96 302.96 218.88H303.12C303.12 218.88 303.2 218.88 303.28 219.04L305.28 223.76C305.28 223.76 305.28 223.92 305.28 224C305.28 224 305.2 224.08 305.12 224.16L273.6 230.48V230.4ZM302.96 219.44C301.28 220.16 290.08 224.88 277.44 229.12L304.72 223.68L302.96 219.44Z"
fill="#101720"
/>
<path
d="M303.04 219.12L273.6 230.16L256.08 187.2L311.52 169.04"
fill="#FFFFFE"
/>
<path
d="M273.6 230.4C273.52 230.4 273.44 230.4 273.36 230.24L255.84 187.28V187.12C255.84 187.12 255.84 187.04 256 186.96L311.44 168.8C311.6 168.8 311.68 168.8 311.76 168.96C311.76 169.12 311.76 169.2 311.6 169.28L256.4 187.36L273.68 229.84L302.96 218.88C303.12 218.88 303.2 218.88 303.28 219.04C303.28 219.2 303.28 219.28 303.12 219.36L273.6 230.4C273.6 230.4 273.6 230.4 273.52 230.4H273.6Z"
fill="#101720"
/>
</svg>
</div>
);
}

View File

@@ -1,21 +1,20 @@
import React from "react";
import { RunStatusBadge } from "../SelectedRunView/components/RunStatusBadge";
import { Text } from "@/components/atoms/Text/Text";
import { Button } from "@/components/atoms/Button/Button";
import {
TrashIcon,
StopIcon,
PlayIcon,
ArrowSquareOutIcon,
} from "@phosphor-icons/react";
import { LibraryAgent } from "@/app/api/__generated__/models/libraryAgent";
import moment from "moment";
import { GraphExecution } from "@/app/api/__generated__/models/graphExecution";
import { useRunDetailHeader } from "./useRunDetailHeader";
import { AgentActionsDropdown } from "../AgentActionsDropdown";
import { LibraryAgent } from "@/app/api/__generated__/models/libraryAgent";
import { Button } from "@/components/atoms/Button/Button";
import { Text } from "@/components/atoms/Text/Text";
import { Dialog } from "@/components/molecules/Dialog/Dialog";
import { Flag, useGetFlag } from "@/services/feature-flags/use-get-flag";
import {
ArrowSquareOutIcon,
PlayIcon,
StopIcon,
TrashIcon,
} from "@phosphor-icons/react";
import moment from "moment";
import { AgentActionsDropdown } from "../AgentActionsDropdown";
import { RunStatusBadge } from "../SelectedRunView/components/RunStatusBadge";
import { ShareRunButton } from "../ShareRunButton/ShareRunButton";
import { useRunDetailHeader } from "./useRunDetailHeader";
type Props = {
agent: LibraryAgent;

View File

@@ -1,24 +1,24 @@
"use client";
import React, { useEffect } from "react";
import { AgentExecutionStatus } from "@/app/api/__generated__/models/agentExecutionStatus";
import type { LibraryAgent } from "@/app/api/__generated__/models/libraryAgent";
import { Skeleton } from "@/components/__legacy__/ui/skeleton";
import { ErrorCard } from "@/components/molecules/ErrorCard/ErrorCard";
import {
TabsLine,
TabsLineContent,
TabsLineList,
TabsLineTrigger,
} from "@/components/molecules/TabsLine/TabsLine";
import { useSelectedRunView } from "./useSelectedRunView";
import type { LibraryAgent } from "@/app/api/__generated__/models/libraryAgent";
import { AgentExecutionStatus } from "@/app/api/__generated__/models/agentExecutionStatus";
import { RunDetailHeader } from "../RunDetailHeader/RunDetailHeader";
import { ErrorCard } from "@/components/molecules/ErrorCard/ErrorCard";
import { Skeleton } from "@/components/__legacy__/ui/skeleton";
import { AgentInputsReadOnly } from "../AgentInputsReadOnly/AgentInputsReadOnly";
import { RunDetailCard } from "../RunDetailCard/RunDetailCard";
import { RunOutputs } from "./components/RunOutputs";
import { PendingReviewsList } from "@/components/organisms/PendingReviewsList/PendingReviewsList";
import { usePendingReviewsForExecution } from "@/hooks/usePendingReviews";
import { parseAsString, useQueryState } from "nuqs";
import { useEffect } from "react";
import { AgentInputsReadOnly } from "../../modals/AgentInputsReadOnly/AgentInputsReadOnly";
import { RunDetailCard } from "../RunDetailCard/RunDetailCard";
import { RunDetailHeader } from "../RunDetailHeader/RunDetailHeader";
import { RunOutputs } from "./components/RunOutputs";
import { useSelectedRunView } from "./useSelectedRunView";
interface Props {
agent: LibraryAgent;

View File

@@ -3,12 +3,12 @@
import type {
OutputMetadata,
OutputRenderer,
} from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/OutputRenderers";
} from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/selected-views/OutputRenderers";
import {
globalRegistry,
OutputActions,
OutputItem,
} from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/OutputRenderers";
} from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/selected-views/OutputRenderers";
import React, { useMemo } from "react";
type OutputsRecord = Record<string, Array<unknown>>;

Some files were not shown because too many files have changed in this diff Show More