mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-03-17 03:00:27 -04:00
Compare commits
12 Commits
ubbe/tailw
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b594a219c | ||
|
|
c51dc7ad99 | ||
|
|
bc6b82218a | ||
|
|
83e49f71cd | ||
|
|
ef446e4fe9 | ||
|
|
7b1e8ed786 | ||
|
|
7ccfff1040 | ||
|
|
81c7685a82 | ||
|
|
3595c6e769 | ||
|
|
1c2953d61b | ||
|
|
755bc84b1a | ||
|
|
ade2baa58f |
@@ -53,6 +53,7 @@ from backend.copilot.tools.models import (
|
||||
UnderstandingUpdatedResponse,
|
||||
)
|
||||
from backend.copilot.tracking import track_user_message
|
||||
from backend.data.redis_client import get_redis_async
|
||||
from backend.data.workspace import get_or_create_workspace
|
||||
from backend.util.exceptions import NotFoundError
|
||||
|
||||
@@ -127,6 +128,7 @@ class SessionSummaryResponse(BaseModel):
|
||||
created_at: str
|
||||
updated_at: str
|
||||
title: str | None = None
|
||||
is_processing: bool
|
||||
|
||||
|
||||
class ListSessionsResponse(BaseModel):
|
||||
@@ -185,6 +187,28 @@ async def list_sessions(
|
||||
"""
|
||||
sessions, total_count = await get_user_sessions(user_id, limit, offset)
|
||||
|
||||
# Batch-check Redis for active stream status on each session
|
||||
processing_set: set[str] = set()
|
||||
if sessions:
|
||||
try:
|
||||
redis = await get_redis_async()
|
||||
pipe = redis.pipeline(transaction=False)
|
||||
for session in sessions:
|
||||
pipe.hget(
|
||||
f"{config.session_meta_prefix}{session.session_id}",
|
||||
"status",
|
||||
)
|
||||
statuses = await pipe.execute()
|
||||
processing_set = {
|
||||
session.session_id
|
||||
for session, st in zip(sessions, statuses)
|
||||
if st == "running"
|
||||
}
|
||||
except Exception:
|
||||
logger.warning(
|
||||
"Failed to fetch processing status from Redis; " "defaulting to empty"
|
||||
)
|
||||
|
||||
return ListSessionsResponse(
|
||||
sessions=[
|
||||
SessionSummaryResponse(
|
||||
@@ -192,6 +216,7 @@ async def list_sessions(
|
||||
created_at=session.started_at.isoformat(),
|
||||
updated_at=session.updated_at.isoformat(),
|
||||
title=session.title,
|
||||
is_processing=session.session_id in processing_set,
|
||||
)
|
||||
for session in sessions
|
||||
],
|
||||
|
||||
@@ -165,7 +165,6 @@ class LibraryAgent(pydantic.BaseModel):
|
||||
id: str
|
||||
graph_id: str
|
||||
graph_version: int
|
||||
owner_user_id: str
|
||||
|
||||
image_url: str | None
|
||||
|
||||
@@ -206,7 +205,9 @@ class LibraryAgent(pydantic.BaseModel):
|
||||
default_factory=list,
|
||||
description="List of recent executions with status, score, and summary",
|
||||
)
|
||||
can_access_graph: bool
|
||||
can_access_graph: bool = pydantic.Field(
|
||||
description="Indicates whether the same user owns the corresponding graph"
|
||||
)
|
||||
is_latest_version: bool
|
||||
is_favorite: bool
|
||||
folder_id: str | None = None
|
||||
@@ -324,7 +325,6 @@ class LibraryAgent(pydantic.BaseModel):
|
||||
id=agent.id,
|
||||
graph_id=agent.agentGraphId,
|
||||
graph_version=agent.agentGraphVersion,
|
||||
owner_user_id=agent.userId,
|
||||
image_url=agent.imageUrl,
|
||||
creator_name=creator_name,
|
||||
creator_image_url=creator_image_url,
|
||||
|
||||
@@ -42,7 +42,6 @@ async def test_get_library_agents_success(
|
||||
id="test-agent-1",
|
||||
graph_id="test-agent-1",
|
||||
graph_version=1,
|
||||
owner_user_id=test_user_id,
|
||||
name="Test Agent 1",
|
||||
description="Test Description 1",
|
||||
image_url=None,
|
||||
@@ -67,7 +66,6 @@ async def test_get_library_agents_success(
|
||||
id="test-agent-2",
|
||||
graph_id="test-agent-2",
|
||||
graph_version=1,
|
||||
owner_user_id=test_user_id,
|
||||
name="Test Agent 2",
|
||||
description="Test Description 2",
|
||||
image_url=None,
|
||||
@@ -131,7 +129,6 @@ async def test_get_favorite_library_agents_success(
|
||||
id="test-agent-1",
|
||||
graph_id="test-agent-1",
|
||||
graph_version=1,
|
||||
owner_user_id=test_user_id,
|
||||
name="Favorite Agent 1",
|
||||
description="Test Favorite Description 1",
|
||||
image_url=None,
|
||||
@@ -184,7 +181,6 @@ def test_add_agent_to_library_success(
|
||||
id="test-library-agent-id",
|
||||
graph_id="test-agent-1",
|
||||
graph_version=1,
|
||||
owner_user_id=test_user_id,
|
||||
name="Test Agent 1",
|
||||
description="Test Description 1",
|
||||
image_url=None,
|
||||
|
||||
@@ -94,3 +94,8 @@ class NotificationPayload(pydantic.BaseModel):
|
||||
|
||||
class OnboardingNotificationPayload(NotificationPayload):
|
||||
step: OnboardingStep | None
|
||||
|
||||
|
||||
class CopilotCompletionPayload(NotificationPayload):
|
||||
session_id: str
|
||||
status: Literal["completed", "failed"]
|
||||
|
||||
@@ -156,10 +156,15 @@ class LlmModel(str, Enum, metaclass=LlmModelMeta):
|
||||
CODESTRAL = "mistralai/codestral-2508"
|
||||
COHERE_COMMAND_R_08_2024 = "cohere/command-r-08-2024"
|
||||
COHERE_COMMAND_R_PLUS_08_2024 = "cohere/command-r-plus-08-2024"
|
||||
COHERE_COMMAND_A_03_2025 = "cohere/command-a-03-2025"
|
||||
COHERE_COMMAND_A_TRANSLATE_08_2025 = "cohere/command-a-translate-08-2025"
|
||||
COHERE_COMMAND_A_REASONING_08_2025 = "cohere/command-a-reasoning-08-2025"
|
||||
COHERE_COMMAND_A_VISION_07_2025 = "cohere/command-a-vision-07-2025"
|
||||
DEEPSEEK_CHAT = "deepseek/deepseek-chat" # Actually: DeepSeek V3
|
||||
DEEPSEEK_R1_0528 = "deepseek/deepseek-r1-0528"
|
||||
PERPLEXITY_SONAR = "perplexity/sonar"
|
||||
PERPLEXITY_SONAR_PRO = "perplexity/sonar-pro"
|
||||
PERPLEXITY_SONAR_REASONING_PRO = "perplexity/sonar-reasoning-pro"
|
||||
PERPLEXITY_SONAR_DEEP_RESEARCH = "perplexity/sonar-deep-research"
|
||||
NOUSRESEARCH_HERMES_3_LLAMA_3_1_405B = "nousresearch/hermes-3-llama-3.1-405b"
|
||||
NOUSRESEARCH_HERMES_3_LLAMA_3_1_70B = "nousresearch/hermes-3-llama-3.1-70b"
|
||||
@@ -167,9 +172,11 @@ class LlmModel(str, Enum, metaclass=LlmModelMeta):
|
||||
AMAZON_NOVA_MICRO_V1 = "amazon/nova-micro-v1"
|
||||
AMAZON_NOVA_PRO_V1 = "amazon/nova-pro-v1"
|
||||
MICROSOFT_WIZARDLM_2_8X22B = "microsoft/wizardlm-2-8x22b"
|
||||
MICROSOFT_PHI_4 = "microsoft/phi-4"
|
||||
GRYPHE_MYTHOMAX_L2_13B = "gryphe/mythomax-l2-13b"
|
||||
META_LLAMA_4_SCOUT = "meta-llama/llama-4-scout"
|
||||
META_LLAMA_4_MAVERICK = "meta-llama/llama-4-maverick"
|
||||
GROK_3 = "x-ai/grok-3"
|
||||
GROK_4 = "x-ai/grok-4"
|
||||
GROK_4_FAST = "x-ai/grok-4-fast"
|
||||
GROK_4_1_FAST = "x-ai/grok-4.1-fast"
|
||||
@@ -461,6 +468,36 @@ MODEL_METADATA = {
|
||||
LlmModel.COHERE_COMMAND_R_PLUS_08_2024: ModelMetadata(
|
||||
"open_router", 128000, 4096, "Command R Plus 08.2024", "OpenRouter", "Cohere", 2
|
||||
),
|
||||
LlmModel.COHERE_COMMAND_A_03_2025: ModelMetadata(
|
||||
"open_router", 256000, 8192, "Command A 03.2025", "OpenRouter", "Cohere", 2
|
||||
),
|
||||
LlmModel.COHERE_COMMAND_A_TRANSLATE_08_2025: ModelMetadata(
|
||||
"open_router",
|
||||
128000,
|
||||
8192,
|
||||
"Command A Translate 08.2025",
|
||||
"OpenRouter",
|
||||
"Cohere",
|
||||
2,
|
||||
),
|
||||
LlmModel.COHERE_COMMAND_A_REASONING_08_2025: ModelMetadata(
|
||||
"open_router",
|
||||
256000,
|
||||
32768,
|
||||
"Command A Reasoning 08.2025",
|
||||
"OpenRouter",
|
||||
"Cohere",
|
||||
3,
|
||||
),
|
||||
LlmModel.COHERE_COMMAND_A_VISION_07_2025: ModelMetadata(
|
||||
"open_router",
|
||||
128000,
|
||||
8192,
|
||||
"Command A Vision 07.2025",
|
||||
"OpenRouter",
|
||||
"Cohere",
|
||||
2,
|
||||
),
|
||||
LlmModel.DEEPSEEK_CHAT: ModelMetadata(
|
||||
"open_router", 64000, 2048, "DeepSeek Chat", "OpenRouter", "DeepSeek", 1
|
||||
),
|
||||
@@ -473,6 +510,15 @@ MODEL_METADATA = {
|
||||
LlmModel.PERPLEXITY_SONAR_PRO: ModelMetadata(
|
||||
"open_router", 200000, 8000, "Sonar Pro", "OpenRouter", "Perplexity", 2
|
||||
),
|
||||
LlmModel.PERPLEXITY_SONAR_REASONING_PRO: ModelMetadata(
|
||||
"open_router",
|
||||
128000,
|
||||
8000,
|
||||
"Sonar Reasoning Pro",
|
||||
"OpenRouter",
|
||||
"Perplexity",
|
||||
2,
|
||||
),
|
||||
LlmModel.PERPLEXITY_SONAR_DEEP_RESEARCH: ModelMetadata(
|
||||
"open_router",
|
||||
128000,
|
||||
@@ -518,6 +564,9 @@ MODEL_METADATA = {
|
||||
LlmModel.MICROSOFT_WIZARDLM_2_8X22B: ModelMetadata(
|
||||
"open_router", 65536, 4096, "WizardLM 2 8x22B", "OpenRouter", "Microsoft", 1
|
||||
),
|
||||
LlmModel.MICROSOFT_PHI_4: ModelMetadata(
|
||||
"open_router", 16384, 16384, "Phi-4", "OpenRouter", "Microsoft", 1
|
||||
),
|
||||
LlmModel.GRYPHE_MYTHOMAX_L2_13B: ModelMetadata(
|
||||
"open_router", 4096, 4096, "MythoMax L2 13B", "OpenRouter", "Gryphe", 1
|
||||
),
|
||||
@@ -527,6 +576,15 @@ MODEL_METADATA = {
|
||||
LlmModel.META_LLAMA_4_MAVERICK: ModelMetadata(
|
||||
"open_router", 1048576, 1000000, "Llama 4 Maverick", "OpenRouter", "Meta", 1
|
||||
),
|
||||
LlmModel.GROK_3: ModelMetadata(
|
||||
"open_router",
|
||||
131072,
|
||||
131072,
|
||||
"Grok 3",
|
||||
"OpenRouter",
|
||||
"xAI",
|
||||
2,
|
||||
),
|
||||
LlmModel.GROK_4: ModelMetadata(
|
||||
"open_router", 256000, 256000, "Grok 4", "OpenRouter", "xAI", 3
|
||||
),
|
||||
|
||||
@@ -4,7 +4,7 @@ from enum import Enum
|
||||
from typing import Any, Literal
|
||||
|
||||
import openai
|
||||
from pydantic import SecretStr
|
||||
from pydantic import SecretStr, field_validator
|
||||
|
||||
from backend.blocks._base import (
|
||||
Block,
|
||||
@@ -13,6 +13,7 @@ from backend.blocks._base import (
|
||||
BlockSchemaInput,
|
||||
BlockSchemaOutput,
|
||||
)
|
||||
from backend.data.block import BlockInput
|
||||
from backend.data.model import (
|
||||
APIKeyCredentials,
|
||||
CredentialsField,
|
||||
@@ -35,6 +36,20 @@ class PerplexityModel(str, Enum):
|
||||
SONAR_DEEP_RESEARCH = "perplexity/sonar-deep-research"
|
||||
|
||||
|
||||
def _sanitize_perplexity_model(value: Any) -> PerplexityModel:
|
||||
"""Return a valid PerplexityModel, falling back to SONAR for invalid values."""
|
||||
if isinstance(value, PerplexityModel):
|
||||
return value
|
||||
try:
|
||||
return PerplexityModel(value)
|
||||
except ValueError:
|
||||
logger.warning(
|
||||
f"Invalid PerplexityModel '{value}', "
|
||||
f"falling back to {PerplexityModel.SONAR.value}"
|
||||
)
|
||||
return PerplexityModel.SONAR
|
||||
|
||||
|
||||
PerplexityCredentials = CredentialsMetaInput[
|
||||
Literal[ProviderName.OPEN_ROUTER], Literal["api_key"]
|
||||
]
|
||||
@@ -73,6 +88,25 @@ class PerplexityBlock(Block):
|
||||
advanced=False,
|
||||
)
|
||||
credentials: PerplexityCredentials = PerplexityCredentialsField()
|
||||
|
||||
@field_validator("model", mode="before")
|
||||
@classmethod
|
||||
def fallback_invalid_model(cls, v: Any) -> PerplexityModel:
|
||||
"""Fall back to SONAR if the model value is not a valid
|
||||
PerplexityModel (e.g. an OpenAI model ID set by the agent
|
||||
generator)."""
|
||||
return _sanitize_perplexity_model(v)
|
||||
|
||||
@classmethod
|
||||
def validate_data(cls, data: BlockInput) -> str | None:
|
||||
"""Sanitize the model field before JSON schema validation so that
|
||||
invalid values are replaced with the default instead of raising a
|
||||
BlockInputError."""
|
||||
model_value = data.get("model")
|
||||
if model_value is not None:
|
||||
data["model"] = _sanitize_perplexity_model(model_value).value
|
||||
return super().validate_data(data)
|
||||
|
||||
system_prompt: str = SchemaField(
|
||||
title="System Prompt",
|
||||
default="",
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
"""Unit tests for PerplexityBlock model fallback behavior."""
|
||||
|
||||
import pytest
|
||||
|
||||
from backend.blocks.perplexity import (
|
||||
TEST_CREDENTIALS_INPUT,
|
||||
PerplexityBlock,
|
||||
PerplexityModel,
|
||||
)
|
||||
|
||||
|
||||
def _make_input(**overrides) -> dict:
|
||||
defaults = {
|
||||
"prompt": "test query",
|
||||
"credentials": TEST_CREDENTIALS_INPUT,
|
||||
}
|
||||
defaults.update(overrides)
|
||||
return defaults
|
||||
|
||||
|
||||
class TestPerplexityModelFallback:
|
||||
"""Tests for fallback_invalid_model field_validator."""
|
||||
|
||||
def test_invalid_model_falls_back_to_sonar(self):
|
||||
inp = PerplexityBlock.Input(**_make_input(model="gpt-5.2-2025-12-11"))
|
||||
assert inp.model == PerplexityModel.SONAR
|
||||
|
||||
def test_another_invalid_model_falls_back_to_sonar(self):
|
||||
inp = PerplexityBlock.Input(**_make_input(model="gpt-4o"))
|
||||
assert inp.model == PerplexityModel.SONAR
|
||||
|
||||
def test_valid_model_string_is_kept(self):
|
||||
inp = PerplexityBlock.Input(**_make_input(model="perplexity/sonar-pro"))
|
||||
assert inp.model == PerplexityModel.SONAR_PRO
|
||||
|
||||
def test_valid_enum_value_is_kept(self):
|
||||
inp = PerplexityBlock.Input(
|
||||
**_make_input(model=PerplexityModel.SONAR_DEEP_RESEARCH)
|
||||
)
|
||||
assert inp.model == PerplexityModel.SONAR_DEEP_RESEARCH
|
||||
|
||||
def test_default_model_when_omitted(self):
|
||||
inp = PerplexityBlock.Input(**_make_input())
|
||||
assert inp.model == PerplexityModel.SONAR
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"model_value",
|
||||
[
|
||||
"perplexity/sonar",
|
||||
"perplexity/sonar-pro",
|
||||
"perplexity/sonar-deep-research",
|
||||
],
|
||||
)
|
||||
def test_all_valid_models_accepted(self, model_value: str):
|
||||
inp = PerplexityBlock.Input(**_make_input(model=model_value))
|
||||
assert inp.model.value == model_value
|
||||
|
||||
|
||||
class TestPerplexityValidateData:
|
||||
"""Tests for validate_data which runs during block execution (before
|
||||
Pydantic instantiation). Invalid models must be sanitized here so
|
||||
JSON schema validation does not reject them."""
|
||||
|
||||
def test_invalid_model_sanitized_before_schema_validation(self):
|
||||
data = _make_input(model="gpt-5.2-2025-12-11")
|
||||
error = PerplexityBlock.Input.validate_data(data)
|
||||
assert error is None
|
||||
assert data["model"] == PerplexityModel.SONAR.value
|
||||
|
||||
def test_valid_model_unchanged_by_validate_data(self):
|
||||
data = _make_input(model="perplexity/sonar-pro")
|
||||
error = PerplexityBlock.Input.validate_data(data)
|
||||
assert error is None
|
||||
assert data["model"] == "perplexity/sonar-pro"
|
||||
|
||||
def test_missing_model_uses_default(self):
|
||||
data = _make_input() # no model key
|
||||
error = PerplexityBlock.Input.validate_data(data)
|
||||
assert error is None
|
||||
inp = PerplexityBlock.Input(**data)
|
||||
assert inp.model == PerplexityModel.SONAR
|
||||
@@ -26,3 +26,17 @@ For other services, search the MCP registry at https://registry.modelcontextprot
|
||||
|
||||
If the server requires credentials, a `SetupRequirementsResponse` is returned with an OAuth
|
||||
login prompt. Once the user completes the flow and confirms, retry the same call immediately.
|
||||
|
||||
### Communication style
|
||||
|
||||
Avoid technical jargon like "MCP server", "OAuth", or "credentials" when talking to the user.
|
||||
Use plain, friendly language instead:
|
||||
|
||||
| Instead of… | Say… |
|
||||
|---|---|
|
||||
| "Let me connect to Sentry's MCP server and discover what tools are available." | "I can connect to Sentry and help identify important issues." |
|
||||
| "Let me connect to Sentry's MCP server now." | "Next, I'll connect to Sentry." |
|
||||
| "The MCP server at mcp.sentry.dev requires authentication. Please connect your credentials to continue." | "To continue, sign in to Sentry and approve access." |
|
||||
| "Sentry's MCP server needs OAuth authentication. You should see a prompt to connect your Sentry account…" | "You should see a prompt to sign in to Sentry. Once connected, I can help surface critical issues right away." |
|
||||
|
||||
Use **"connect to [Service]"** or **"sign in to [Service]"** — never "MCP server", "OAuth", or "credentials".
|
||||
|
||||
@@ -23,6 +23,11 @@ from typing import Any, Literal
|
||||
|
||||
import orjson
|
||||
|
||||
from backend.api.model import CopilotCompletionPayload
|
||||
from backend.data.notification_bus import (
|
||||
AsyncRedisNotificationEventBus,
|
||||
NotificationEvent,
|
||||
)
|
||||
from backend.data.redis_client import get_redis_async
|
||||
|
||||
from .config import ChatConfig
|
||||
@@ -38,6 +43,7 @@ from .response_model import (
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
config = ChatConfig()
|
||||
_notification_bus = AsyncRedisNotificationEventBus()
|
||||
|
||||
# Track background tasks for this pod (just the asyncio.Task reference, not subscribers)
|
||||
_local_sessions: dict[str, asyncio.Task] = {}
|
||||
@@ -745,6 +751,29 @@ async def mark_session_completed(
|
||||
|
||||
# Clean up local session reference if exists
|
||||
_local_sessions.pop(session_id, None)
|
||||
|
||||
# Publish copilot completion notification via WebSocket
|
||||
if meta:
|
||||
parsed = _parse_session_meta(meta, session_id)
|
||||
if parsed.user_id:
|
||||
try:
|
||||
await _notification_bus.publish(
|
||||
NotificationEvent(
|
||||
user_id=parsed.user_id,
|
||||
payload=CopilotCompletionPayload(
|
||||
type="copilot_completion",
|
||||
event="session_completed",
|
||||
session_id=session_id,
|
||||
status=status,
|
||||
),
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning(
|
||||
f"Failed to publish copilot completion notification "
|
||||
f"for session {session_id}: {e}"
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
@@ -829,8 +829,12 @@ class AgentFixer:
|
||||
|
||||
For nodes whose block has category "AI", this function ensures that the
|
||||
input_default has a "model" parameter set to one of the allowed models.
|
||||
If missing or set to an unsupported value, it is replaced with
|
||||
default_model.
|
||||
If missing or set to an unsupported value, it is replaced with the
|
||||
appropriate default.
|
||||
|
||||
Blocks that define their own ``enum`` constraint on the ``model`` field
|
||||
in their inputSchema (e.g. PerplexityBlock) are validated against that
|
||||
enum instead of the generic allowed set.
|
||||
|
||||
Args:
|
||||
agent: The agent dictionary to fix
|
||||
@@ -840,7 +844,7 @@ class AgentFixer:
|
||||
Returns:
|
||||
The fixed agent dictionary
|
||||
"""
|
||||
allowed_models = {"gpt-4o", "claude-opus-4-6"}
|
||||
generic_allowed_models = {"gpt-4o", "claude-opus-4-6"}
|
||||
|
||||
# Create a mapping of block_id to block for quick lookup
|
||||
block_map = {block.get("id"): block for block in blocks}
|
||||
@@ -868,20 +872,36 @@ class AgentFixer:
|
||||
input_default = node.get("input_default", {})
|
||||
current_model = input_default.get("model")
|
||||
|
||||
# Determine allowed models and default from the block's schema.
|
||||
# Blocks with a block-specific enum on the model field (e.g.
|
||||
# PerplexityBlock) use their own enum values; others use the
|
||||
# generic set.
|
||||
model_schema = (
|
||||
block.get("inputSchema", {}).get("properties", {}).get("model", {})
|
||||
)
|
||||
block_model_enum = model_schema.get("enum")
|
||||
|
||||
if block_model_enum:
|
||||
allowed_models = set(block_model_enum)
|
||||
fallback_model = model_schema.get("default", block_model_enum[0])
|
||||
else:
|
||||
allowed_models = generic_allowed_models
|
||||
fallback_model = default_model
|
||||
|
||||
if current_model not in allowed_models:
|
||||
block_name = block.get("name", "Unknown AI Block")
|
||||
if current_model is None:
|
||||
self.add_fix_log(
|
||||
f"Added model parameter '{default_model}' to AI "
|
||||
f"Added model parameter '{fallback_model}' to AI "
|
||||
f"block node {node_id} ({block_name})"
|
||||
)
|
||||
else:
|
||||
self.add_fix_log(
|
||||
f"Replaced unsupported model '{current_model}' "
|
||||
f"with '{default_model}' on AI block node "
|
||||
f"with '{fallback_model}' on AI block node "
|
||||
f"{node_id} ({block_name})"
|
||||
)
|
||||
input_default["model"] = default_model
|
||||
input_default["model"] = fallback_model
|
||||
node["input_default"] = input_default
|
||||
fixed_count += 1
|
||||
|
||||
|
||||
@@ -475,6 +475,111 @@ class TestFixAiModelParameter:
|
||||
|
||||
assert result["nodes"][0]["input_default"]["model"] == "claude-opus-4-6"
|
||||
|
||||
def test_block_specific_enum_uses_block_default(self):
|
||||
"""Blocks with their own model enum (e.g. PerplexityBlock) should use
|
||||
the block's allowed models and default, not the generic ones."""
|
||||
fixer = AgentFixer()
|
||||
block_id = generate_uuid()
|
||||
node = _make_node(
|
||||
node_id="n1",
|
||||
block_id=block_id,
|
||||
input_default={"model": "gpt-5.2-2025-12-11"},
|
||||
)
|
||||
agent = _make_agent(nodes=[node])
|
||||
|
||||
blocks = [
|
||||
{
|
||||
"id": block_id,
|
||||
"name": "PerplexityBlock",
|
||||
"categories": [{"category": "AI"}],
|
||||
"inputSchema": {
|
||||
"properties": {
|
||||
"model": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"perplexity/sonar",
|
||||
"perplexity/sonar-pro",
|
||||
"perplexity/sonar-deep-research",
|
||||
],
|
||||
"default": "perplexity/sonar",
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
result = fixer.fix_ai_model_parameter(agent, blocks)
|
||||
|
||||
assert result["nodes"][0]["input_default"]["model"] == "perplexity/sonar"
|
||||
|
||||
def test_block_specific_enum_valid_model_unchanged(self):
|
||||
"""A valid block-specific model should not be replaced."""
|
||||
fixer = AgentFixer()
|
||||
block_id = generate_uuid()
|
||||
node = _make_node(
|
||||
node_id="n1",
|
||||
block_id=block_id,
|
||||
input_default={"model": "perplexity/sonar-pro"},
|
||||
)
|
||||
agent = _make_agent(nodes=[node])
|
||||
|
||||
blocks = [
|
||||
{
|
||||
"id": block_id,
|
||||
"name": "PerplexityBlock",
|
||||
"categories": [{"category": "AI"}],
|
||||
"inputSchema": {
|
||||
"properties": {
|
||||
"model": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"perplexity/sonar",
|
||||
"perplexity/sonar-pro",
|
||||
"perplexity/sonar-deep-research",
|
||||
],
|
||||
"default": "perplexity/sonar",
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
result = fixer.fix_ai_model_parameter(agent, blocks)
|
||||
|
||||
assert result["nodes"][0]["input_default"]["model"] == "perplexity/sonar-pro"
|
||||
|
||||
def test_block_specific_enum_missing_model_gets_block_default(self):
|
||||
"""Missing model on a block with enum should use the block's default."""
|
||||
fixer = AgentFixer()
|
||||
block_id = generate_uuid()
|
||||
node = _make_node(node_id="n1", block_id=block_id, input_default={})
|
||||
agent = _make_agent(nodes=[node])
|
||||
|
||||
blocks = [
|
||||
{
|
||||
"id": block_id,
|
||||
"name": "PerplexityBlock",
|
||||
"categories": [{"category": "AI"}],
|
||||
"inputSchema": {
|
||||
"properties": {
|
||||
"model": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"perplexity/sonar",
|
||||
"perplexity/sonar-pro",
|
||||
"perplexity/sonar-deep-research",
|
||||
],
|
||||
"default": "perplexity/sonar",
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
]
|
||||
|
||||
result = fixer.fix_ai_model_parameter(agent, blocks)
|
||||
|
||||
assert result["nodes"][0]["input_default"]["model"] == "perplexity/sonar"
|
||||
|
||||
|
||||
class TestFixAgentExecutorBlocks:
|
||||
"""Tests for fix_agent_executor_blocks."""
|
||||
|
||||
@@ -34,6 +34,11 @@ logger = logging.getLogger(__name__)
|
||||
_AUTH_STATUS_CODES = {401, 403}
|
||||
|
||||
|
||||
def _service_name(host: str) -> str:
|
||||
"""Strip the 'mcp.' prefix from an MCP hostname: 'mcp.sentry.dev' → 'sentry.dev'"""
|
||||
return host[4:] if host.startswith("mcp.") else host
|
||||
|
||||
|
||||
class RunMCPToolTool(BaseTool):
|
||||
"""
|
||||
Tool for discovering and executing tools on any MCP server.
|
||||
@@ -303,8 +308,8 @@ class RunMCPToolTool(BaseTool):
|
||||
)
|
||||
return ErrorResponse(
|
||||
message=(
|
||||
f"The MCP server at {server_host(server_url)} requires authentication, "
|
||||
"but no credential configuration was found."
|
||||
f"Unable to connect to {_service_name(server_host(server_url))} "
|
||||
"— no credentials configured."
|
||||
),
|
||||
session_id=session_id,
|
||||
)
|
||||
@@ -312,15 +317,13 @@ class RunMCPToolTool(BaseTool):
|
||||
missing_creds_list = list(missing_creds_dict.values())
|
||||
|
||||
host = server_host(server_url)
|
||||
service = _service_name(host)
|
||||
return SetupRequirementsResponse(
|
||||
message=(
|
||||
f"The MCP server at {host} requires authentication. "
|
||||
"Please connect your credentials to continue."
|
||||
),
|
||||
message=(f"To continue, sign in to {service} and approve access."),
|
||||
session_id=session_id,
|
||||
setup_info=SetupInfo(
|
||||
agent_id=server_url,
|
||||
agent_name=f"MCP: {host}",
|
||||
agent_name=service,
|
||||
user_readiness=UserReadiness(
|
||||
has_all_credentials=False,
|
||||
missing_credentials=missing_creds_dict,
|
||||
|
||||
@@ -756,4 +756,4 @@ async def test_build_setup_requirements_returns_setup_response():
|
||||
)
|
||||
assert isinstance(result, SetupRequirementsResponse)
|
||||
assert result.setup_info.agent_id == _SERVER_URL
|
||||
assert "authentication" in result.message.lower()
|
||||
assert "sign in" in result.message.lower()
|
||||
|
||||
@@ -116,10 +116,15 @@ MODEL_COST: dict[LlmModel, int] = {
|
||||
LlmModel.CODESTRAL: 1,
|
||||
LlmModel.COHERE_COMMAND_R_08_2024: 1,
|
||||
LlmModel.COHERE_COMMAND_R_PLUS_08_2024: 3,
|
||||
LlmModel.COHERE_COMMAND_A_03_2025: 3,
|
||||
LlmModel.COHERE_COMMAND_A_TRANSLATE_08_2025: 3,
|
||||
LlmModel.COHERE_COMMAND_A_REASONING_08_2025: 6,
|
||||
LlmModel.COHERE_COMMAND_A_VISION_07_2025: 3,
|
||||
LlmModel.DEEPSEEK_CHAT: 2,
|
||||
LlmModel.DEEPSEEK_R1_0528: 1,
|
||||
LlmModel.PERPLEXITY_SONAR: 1,
|
||||
LlmModel.PERPLEXITY_SONAR_PRO: 5,
|
||||
LlmModel.PERPLEXITY_SONAR_REASONING_PRO: 5,
|
||||
LlmModel.PERPLEXITY_SONAR_DEEP_RESEARCH: 10,
|
||||
LlmModel.NOUSRESEARCH_HERMES_3_LLAMA_3_1_405B: 1,
|
||||
LlmModel.NOUSRESEARCH_HERMES_3_LLAMA_3_1_70B: 1,
|
||||
@@ -127,6 +132,7 @@ MODEL_COST: dict[LlmModel, int] = {
|
||||
LlmModel.AMAZON_NOVA_MICRO_V1: 1,
|
||||
LlmModel.AMAZON_NOVA_PRO_V1: 1,
|
||||
LlmModel.MICROSOFT_WIZARDLM_2_8X22B: 1,
|
||||
LlmModel.MICROSOFT_PHI_4: 1,
|
||||
LlmModel.GRYPHE_MYTHOMAX_L2_13B: 1,
|
||||
LlmModel.META_LLAMA_4_SCOUT: 1,
|
||||
LlmModel.META_LLAMA_4_MAVERICK: 1,
|
||||
@@ -134,6 +140,7 @@ MODEL_COST: dict[LlmModel, int] = {
|
||||
LlmModel.LLAMA_API_LLAMA4_MAVERICK: 1,
|
||||
LlmModel.LLAMA_API_LLAMA3_3_8B: 1,
|
||||
LlmModel.LLAMA_API_LLAMA3_3_70B: 1,
|
||||
LlmModel.GROK_3: 3,
|
||||
LlmModel.GROK_4: 9,
|
||||
LlmModel.GROK_4_FAST: 1,
|
||||
LlmModel.GROK_4_1_FAST: 1,
|
||||
|
||||
@@ -8,6 +8,8 @@ from backend.api.model import NotificationPayload
|
||||
from backend.data.event_bus import AsyncRedisEventBus
|
||||
from backend.util.settings import Settings
|
||||
|
||||
_settings = Settings()
|
||||
|
||||
|
||||
class NotificationEvent(BaseModel):
|
||||
"""Generic notification event destined for websocket delivery."""
|
||||
@@ -26,7 +28,7 @@ class AsyncRedisNotificationEventBus(AsyncRedisEventBus[NotificationEvent]):
|
||||
|
||||
@property
|
||||
def event_bus_name(self) -> str:
|
||||
return Settings().config.notification_event_bus_name
|
||||
return _settings.config.notification_event_bus_name
|
||||
|
||||
async def publish(self, event: NotificationEvent) -> None:
|
||||
await self.publish_event(event, event.user_id)
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
-- Fix PerplexityBlock nodes that have invalid model values (e.g. gpt-4o,
|
||||
-- gpt-5.2-2025-12-11) set by the agent generator. Defaults them to the
|
||||
-- standard "perplexity/sonar" model.
|
||||
--
|
||||
-- PerplexityBlock ID: c8a5f2e9-8b3d-4a7e-9f6c-1d5e3c9b7a4f
|
||||
-- Valid models: perplexity/sonar, perplexity/sonar-pro, perplexity/sonar-deep-research
|
||||
|
||||
UPDATE "AgentNode"
|
||||
SET "constantInput" = JSONB_SET(
|
||||
"constantInput"::jsonb,
|
||||
'{model}',
|
||||
'"perplexity/sonar"'::jsonb
|
||||
)
|
||||
WHERE "agentBlockId" = 'c8a5f2e9-8b3d-4a7e-9f6c-1d5e3c9b7a4f'
|
||||
AND "constantInput"::jsonb ? 'model'
|
||||
AND "constantInput"::jsonb->>'model' NOT IN (
|
||||
'perplexity/sonar',
|
||||
'perplexity/sonar-pro',
|
||||
'perplexity/sonar-deep-research'
|
||||
);
|
||||
|
||||
-- Update AgentPreset input overrides (stored in AgentNodeExecutionInputOutput).
|
||||
-- The table links to AgentNode through AgentNodeExecution, not directly.
|
||||
UPDATE "AgentNodeExecutionInputOutput" io
|
||||
SET "data" = JSONB_SET(
|
||||
io."data"::jsonb,
|
||||
'{model}',
|
||||
'"perplexity/sonar"'::jsonb
|
||||
)
|
||||
FROM "AgentNodeExecution" exe
|
||||
JOIN "AgentNode" n ON n."id" = exe."agentNodeId"
|
||||
WHERE io."agentPresetId" IS NOT NULL
|
||||
AND (io."referencedByInputExecId" = exe."id" OR io."referencedByOutputExecId" = exe."id")
|
||||
AND n."agentBlockId" = 'c8a5f2e9-8b3d-4a7e-9f6c-1d5e3c9b7a4f'
|
||||
AND io."data"::jsonb ? 'model'
|
||||
AND io."data"::jsonb->>'model' NOT IN (
|
||||
'perplexity/sonar',
|
||||
'perplexity/sonar-pro',
|
||||
'perplexity/sonar-deep-research'
|
||||
);
|
||||
@@ -4,7 +4,6 @@
|
||||
"id": "test-agent-1",
|
||||
"graph_id": "test-agent-1",
|
||||
"graph_version": 1,
|
||||
"owner_user_id": "3e53486c-cf57-477e-ba2a-cb02dc828e1a",
|
||||
"image_url": null,
|
||||
"creator_name": "Test Creator",
|
||||
"creator_image_url": "",
|
||||
@@ -51,7 +50,6 @@
|
||||
"id": "test-agent-2",
|
||||
"graph_id": "test-agent-2",
|
||||
"graph_version": 1,
|
||||
"owner_user_id": "3e53486c-cf57-477e-ba2a-cb02dc828e1a",
|
||||
"image_url": null,
|
||||
"creator_name": "Test Creator",
|
||||
"creator_image_url": "",
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
{
|
||||
"plugins": ["prettier-plugin-tailwindcss"],
|
||||
"tailwindStylesheet": "./src/app/globals.css"
|
||||
"plugins": ["prettier-plugin-tailwindcss"]
|
||||
}
|
||||
|
||||
@@ -120,6 +120,8 @@
|
||||
"sonner": "2.0.7",
|
||||
"streamdown": "2.1.0",
|
||||
"tailwind-merge": "2.6.0",
|
||||
"tailwind-scrollbar": "3.1.0",
|
||||
"tailwindcss-animate": "1.0.7",
|
||||
"use-stick-to-bottom": "1.1.2",
|
||||
"uuid": "11.1.0",
|
||||
"vaul": "1.1.2",
|
||||
@@ -135,7 +137,6 @@
|
||||
"@storybook/addon-links": "9.1.5",
|
||||
"@storybook/addon-onboarding": "9.1.5",
|
||||
"@storybook/nextjs": "9.1.5",
|
||||
"@tailwindcss/postcss": "4.2.1",
|
||||
"@tanstack/eslint-plugin-query": "5.91.2",
|
||||
"@tanstack/react-query-devtools": "5.90.2",
|
||||
"@testing-library/dom": "10.4.1",
|
||||
@@ -164,12 +165,10 @@
|
||||
"pbkdf2": "3.1.5",
|
||||
"postcss": "8.5.6",
|
||||
"prettier": "3.6.2",
|
||||
"prettier-plugin-tailwindcss": "0.7.2",
|
||||
"prettier-plugin-tailwindcss": "0.7.1",
|
||||
"require-in-the-middle": "8.0.1",
|
||||
"storybook": "9.1.5",
|
||||
"tailwind-scrollbar": "4.0.2",
|
||||
"tailwindcss": "4.2.1",
|
||||
"tw-animate-css": "1.4.0",
|
||||
"tailwindcss": "3.4.17",
|
||||
"typescript": "5.9.3",
|
||||
"vite-tsconfig-paths": "6.0.4",
|
||||
"vitest": "4.0.17"
|
||||
|
||||
706
autogpt_platform/frontend/pnpm-lock.yaml
generated
706
autogpt_platform/frontend/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/** @type {import('postcss-load-config').Config} */
|
||||
const config = {
|
||||
plugins: {
|
||||
"@tailwindcss/postcss": {},
|
||||
tailwindcss: {},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@ export function RunAgentHint(props: RunAgentHintProps) {
|
||||
<div className="ml-[104px] w-[481px] pl-5">
|
||||
<div className="flex flex-col">
|
||||
<OnboardingText variant="header">Run your first agent</OnboardingText>
|
||||
<span className="mt-9 text-base leading-normal font-normal text-zinc-600">
|
||||
<span className="mt-9 text-base font-normal leading-normal text-zinc-600">
|
||||
A 'run' is when your agent starts working on a task
|
||||
</span>
|
||||
<span className="mt-4 text-base leading-normal font-normal text-zinc-600">
|
||||
<span className="mt-4 text-base font-normal leading-normal text-zinc-600">
|
||||
Click on <b>New Run</b> below to try it out
|
||||
</span>
|
||||
|
||||
@@ -35,7 +35,7 @@ export function RunAgentHint(props: RunAgentHintProps) {
|
||||
<line x1="8" y1="16" x2="24" y2="16" />
|
||||
</g>
|
||||
</svg>
|
||||
<span className="ml-3 font-sans text-[19px] leading-normal font-medium text-violet-700">
|
||||
<span className="ml-3 font-sans text-[19px] font-medium leading-normal text-violet-700">
|
||||
New run
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -8,8 +8,8 @@ type Props = {
|
||||
|
||||
export function SelectedAgentCard(props: Props) {
|
||||
return (
|
||||
<div className="fixed top-1/2 left-1/4 w-[481px] -translate-x-1/2 -translate-y-1/2">
|
||||
<div className="h-[156px] w-[481px] rounded-xl bg-white px-6 pt-4 pb-5">
|
||||
<div className="fixed left-1/4 top-1/2 w-[481px] -translate-x-1/2 -translate-y-1/2">
|
||||
<div className="h-[156px] w-[481px] rounded-xl bg-white px-6 pb-5 pt-4">
|
||||
<span className="font-sans text-xs font-medium tracking-wide text-zinc-500">
|
||||
SELECTED AGENT
|
||||
</span>
|
||||
@@ -24,7 +24,7 @@ export function SelectedAgentCard(props: Props) {
|
||||
{/* Right content */}
|
||||
<div className="ml-3 flex flex-1 flex-col">
|
||||
<div className="mb-2 flex flex-col items-start">
|
||||
<span className="data-sentry-unmask w-[292px] truncate font-sans text-[14px] leading-tight font-medium text-zinc-800">
|
||||
<span className="data-sentry-unmask w-[292px] truncate font-sans text-[14px] font-medium leading-tight text-zinc-800">
|
||||
{props.storeAgent.agent_name}
|
||||
</span>
|
||||
<span className="data-sentry-unmask font-norma w-[292px] truncate font-sans text-xs text-zinc-600">
|
||||
@@ -32,11 +32,11 @@ export function SelectedAgentCard(props: Props) {
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex w-[292px] items-center justify-between">
|
||||
<span className="truncate font-sans text-xs leading-tight font-normal text-zinc-600">
|
||||
<span className="truncate font-sans text-xs font-normal leading-tight text-zinc-600">
|
||||
{props.storeAgent.runs.toLocaleString("en-US")} runs
|
||||
</span>
|
||||
<StarRating
|
||||
className="font-sans text-xs leading-tight font-normal text-zinc-600"
|
||||
className="font-sans text-xs font-normal leading-tight text-zinc-600"
|
||||
starSize={12}
|
||||
rating={props.storeAgent.rating || 0}
|
||||
/>
|
||||
|
||||
@@ -63,15 +63,15 @@ export default function Page() {
|
||||
<OnboardingText variant="header">
|
||||
Provide details for your agent
|
||||
</OnboardingText>
|
||||
<span className="mt-9 text-base leading-normal font-normal text-zinc-600">
|
||||
<span className="mt-9 text-base font-normal leading-normal text-zinc-600">
|
||||
Give your agent the details it needs to work—just enter <br />
|
||||
the key information and get started.
|
||||
</span>
|
||||
<span className="mt-4 text-base leading-normal font-normal text-zinc-600">
|
||||
<span className="mt-4 text-base font-normal leading-normal text-zinc-600">
|
||||
When you're done, click <b>Run Agent</b>.
|
||||
</span>
|
||||
|
||||
<Card className="mt-4 agpt-box">
|
||||
<Card className="agpt-box mt-4">
|
||||
<CardHeader>
|
||||
<CardTitle className="font-poppins text-lg">Input</CardTitle>
|
||||
</CardHeader>
|
||||
|
||||
@@ -92,7 +92,7 @@ export default function Page() {
|
||||
</h1>
|
||||
<p
|
||||
className={cn(
|
||||
"mt-4 mb-16 font-poppins text-2xl font-medium text-violet-800 transition-opacity duration-500",
|
||||
"mb-16 mt-4 font-poppins text-2xl font-medium text-violet-800 transition-opacity duration-500",
|
||||
showSubtext ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -66,12 +66,12 @@ export default function OnboardingAgentCard({
|
||||
{/* Text content wrapper */}
|
||||
<div>
|
||||
{/* Title - 2 lines max */}
|
||||
<p className="data-sentry-unmask text-md line-clamp-2 max-h-[50px] font-sans text-base leading-normal font-medium text-zinc-800">
|
||||
<p className="data-sentry-unmask text-md line-clamp-2 max-h-[50px] font-sans text-base font-medium leading-normal text-zinc-800">
|
||||
{agent_name}
|
||||
</p>
|
||||
|
||||
{/* Author - single line with truncate */}
|
||||
<p className="data-sentry-unmask truncate text-sm leading-normal font-normal text-zinc-600">
|
||||
<p className="data-sentry-unmask truncate text-sm font-normal leading-normal text-zinc-600">
|
||||
by {creator}
|
||||
</p>
|
||||
|
||||
|
||||
@@ -31,10 +31,10 @@ function OnboardingGridElement({
|
||||
imageContain
|
||||
className="h-12 w-12 rounded-lg"
|
||||
/>
|
||||
<span className="text-md mt-4 w-full text-left leading-normal font-medium text-[#121212]">
|
||||
<span className="text-md mt-4 w-full text-left font-medium leading-normal text-[#121212]">
|
||||
{name}
|
||||
</span>
|
||||
<span className="w-full text-left text-[11.5px] leading-5 font-normal text-zinc-500">
|
||||
<span className="w-full text-left text-[11.5px] font-normal leading-5 text-zinc-500">
|
||||
{text}
|
||||
</span>
|
||||
<div
|
||||
|
||||
@@ -17,9 +17,9 @@ export default function OnboardingInput({
|
||||
<input
|
||||
className={cn(
|
||||
className,
|
||||
"font-poppin relative h-[50px] w-[512px] rounded-[25px] border border-transparent bg-white px-4 text-sm leading-normal font-normal text-zinc-900",
|
||||
"font-poppin relative h-[50px] w-[512px] rounded-[25px] border border-transparent bg-white px-4 text-sm font-normal leading-normal text-zinc-900",
|
||||
"transition-all duration-200 ease-in-out placeholder:text-zinc-400",
|
||||
"focus:border-transparent focus:bg-[#F5F3FF80] focus:ring-2 focus:ring-violet-700 focus:outline-hidden",
|
||||
"focus:border-transparent focus:bg-[#F5F3FF80] focus:outline-none focus:ring-2 focus:ring-violet-700",
|
||||
)}
|
||||
placeholder={placeholder}
|
||||
value={value}
|
||||
|
||||
@@ -46,7 +46,7 @@ export function OnboardingListElement({
|
||||
ref={inputRef}
|
||||
className={cn(
|
||||
selected ? "text-zinc-600" : "text-zinc-400",
|
||||
"font-poppin w-full border-0 bg-[#F5F3FF80] text-sm focus:outline-hidden",
|
||||
"font-poppin w-full border-0 bg-[#F5F3FF80] text-sm focus:outline-none",
|
||||
)}
|
||||
placeholder="Please specify"
|
||||
value={content}
|
||||
|
||||
@@ -15,7 +15,7 @@ export function OnboardingStep({
|
||||
return (
|
||||
<div className="relative flex min-h-screen w-full flex-col">
|
||||
{dotted && (
|
||||
<div className="absolute left-1/2 h-full w-1/2 bg-white bg-[radial-gradient(#e5e7eb77_1px,transparent_1px)] bg-size-[10px_10px]"></div>
|
||||
<div className="absolute left-1/2 h-full w-1/2 bg-white bg-[radial-gradient(#e5e7eb77_1px,transparent_1px)] [background-size:10px_10px]"></div>
|
||||
)}
|
||||
<div className="z-10 flex flex-col items-center">{children}</div>
|
||||
</div>
|
||||
@@ -48,7 +48,7 @@ export function OnboardingHeader({
|
||||
</div>
|
||||
|
||||
{!transparent && (
|
||||
<div className="h-4 w-full bg-linear-to-b from-gray-100 via-gray-100/50 to-transparent" />
|
||||
<div className="h-4 w-full bg-gradient-to-b from-gray-100 via-gray-100/50 to-transparent" />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
@@ -57,7 +57,7 @@ export function OnboardingHeader({
|
||||
export function OnboardingFooter({ children }: { children?: ReactNode }) {
|
||||
return (
|
||||
<div className="sticky bottom-0 z-10 w-full">
|
||||
<div className="h-4 w-full bg-linear-to-t from-gray-100 via-gray-100/50 to-transparent" />
|
||||
<div className="h-4 w-full bg-gradient-to-t from-gray-100 via-gray-100/50 to-transparent" />
|
||||
<div className="flex justify-center bg-gray-100">
|
||||
<div className="px-5 py-5">{children}</div>
|
||||
</div>
|
||||
|
||||
@@ -46,7 +46,7 @@ export default function StarRating({
|
||||
)}
|
||||
>
|
||||
{/* Display numerical rating */}
|
||||
<span className="mt-0.5 mr-1">{roundedRating}</span>
|
||||
<span className="mr-1 mt-0.5">{roundedRating}</span>
|
||||
|
||||
{/* Display stars */}
|
||||
{stars.map((starType, index) => {
|
||||
|
||||
@@ -16,7 +16,7 @@ function ExecutionAnalyticsDashboard() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-lg border bg-white p-6 shadow-xs">
|
||||
<div className="rounded-lg border bg-white p-6 shadow-sm">
|
||||
<h2 className="mb-4 text-xl font-semibold">
|
||||
Execution Analytics & Accuracy Monitoring
|
||||
</h2>
|
||||
|
||||
@@ -12,7 +12,7 @@ export const BuilderActions = memo(() => {
|
||||
return (
|
||||
<div
|
||||
data-id="builder-actions"
|
||||
className="absolute bottom-4 left-[50%] z-100 flex -translate-x-1/2 items-center gap-4 rounded-full bg-white p-2 px-2 shadow-lg"
|
||||
className="absolute bottom-4 left-[50%] z-[100] flex -translate-x-1/2 items-center gap-4 rounded-full bg-white p-2 px-2 shadow-lg"
|
||||
>
|
||||
<AgentOutputs flowID={flowID} />
|
||||
<RunGraph flowID={flowID} />
|
||||
|
||||
@@ -112,7 +112,7 @@ export const AgentOutputs = ({ flowID }: { flowID: string | null }) => {
|
||||
{outputs.length > 0 && <OutputActions items={actionItems} />}
|
||||
</div>
|
||||
</SheetHeader>
|
||||
<div className="grow overflow-y-auto px-2 py-2">
|
||||
<div className="flex-grow overflow-y-auto px-2 py-2">
|
||||
<ScrollArea className="h-full overflow-auto pr-4">
|
||||
<div className="space-y-6">
|
||||
{outputs && outputs.length > 0 ? (
|
||||
|
||||
@@ -71,7 +71,7 @@ export function DraftRecoveryPopup({
|
||||
{isOpen && (
|
||||
<motion.div
|
||||
ref={popupRef}
|
||||
className={cn("absolute top-4 left-1/2 z-50")}
|
||||
className={cn("absolute left-1/2 top-4 z-50")}
|
||||
initial={{
|
||||
opacity: 0,
|
||||
x: "-50%",
|
||||
|
||||
@@ -41,7 +41,7 @@ function SafeModeButton({
|
||||
<Tooltip delayDuration={100}>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant={isEnabled ? "primary" : "outline-solid"}
|
||||
variant={isEnabled ? "primary" : "outline"}
|
||||
size="small"
|
||||
onClick={onToggle}
|
||||
disabled={isPending}
|
||||
|
||||
@@ -123,7 +123,7 @@ export const Flow = () => {
|
||||
{graph && (
|
||||
<FloatingSafeModeToggle
|
||||
graph={graph}
|
||||
className="top-32 right-2 p-2"
|
||||
className="right-2 top-32 p-2"
|
||||
/>
|
||||
)}
|
||||
<DraftRecoveryPopup isInitialLoadComplete={isInitialLoadComplete} />
|
||||
|
||||
@@ -24,7 +24,7 @@ export const GraphLoadingBox = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="absolute top-[50%] left-[50%] z-99 -translate-x-1/2 -translate-y-1/2">
|
||||
<div className="absolute left-[50%] top-[50%] z-[99] -translate-x-1/2 -translate-y-1/2">
|
||||
<div className="flex flex-col items-center gap-4 rounded-xlarge border border-gray-200 bg-white p-8 shadow-lg dark:border-gray-700 dark:bg-slate-800">
|
||||
<div className="relative h-12 w-12">
|
||||
<div className="absolute inset-0 animate-spin rounded-full border-4 border-zinc-100 border-t-zinc-400 dark:border-gray-700 dark:border-t-blue-400"></div>
|
||||
|
||||
@@ -43,7 +43,7 @@ export const RunningBackground = () => {
|
||||
}}
|
||||
></div>
|
||||
<div
|
||||
className="animate-pulse-border absolute inset-0 bg-transparent blur-xs"
|
||||
className="animate-pulse-border absolute inset-0 bg-transparent blur-sm"
|
||||
style={{
|
||||
borderWidth: "6px",
|
||||
borderStyle: "solid",
|
||||
|
||||
@@ -27,7 +27,7 @@ export const TriggerAgentBanner = () => {
|
||||
);
|
||||
|
||||
return (
|
||||
<Alert className="absolute bottom-4 left-1/2 z-20 w-auto -translate-x-1/2 rounded-xlarge select-none">
|
||||
<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
|
||||
|
||||
@@ -78,9 +78,9 @@ const CustomEdge = ({
|
||||
interactionWidth={0}
|
||||
markerEnd={markerEnd}
|
||||
className={cn(
|
||||
isStatic && "stroke-[1.5px]! [stroke-dasharray:6]",
|
||||
isStatic && "!stroke-[1.5px] [stroke-dasharray:6]",
|
||||
isBroken
|
||||
? "stroke-red-500! stroke-[2px]! [stroke-dasharray:4]"
|
||||
? "!stroke-red-500 !stroke-[2px] [stroke-dasharray:4]"
|
||||
: selected
|
||||
? "stroke-zinc-800"
|
||||
: edgeColorClass
|
||||
|
||||
@@ -25,7 +25,7 @@ const InputNodeHandle = ({
|
||||
type={"target"}
|
||||
position={Position.Left}
|
||||
id={cleanedHandleId}
|
||||
className={"mr-2 -ml-6"}
|
||||
className={"-ml-6 mr-2"}
|
||||
data-tutorial-id={`input-handler-${nodeId}-${cleanedHandleId}`}
|
||||
>
|
||||
<div className="pointer-events-none">
|
||||
|
||||
@@ -38,7 +38,7 @@ export function NodeAdvancedToggle({
|
||||
<Text
|
||||
variant="body"
|
||||
as="span"
|
||||
className="flex items-center gap-2 font-semibold! text-slate-700"
|
||||
className="flex items-center gap-2 !font-semibold text-slate-700"
|
||||
>
|
||||
Advanced{" "}
|
||||
<CaretDownIcon
|
||||
|
||||
@@ -29,7 +29,7 @@ export const NodeCost = ({
|
||||
return (
|
||||
<div className="mr-3 flex items-center gap-1 text-base font-light">
|
||||
<CoinIcon className="h-3 w-3" />
|
||||
<Text variant="small" className="font-medium!">
|
||||
<Text variant="small" className="!font-medium">
|
||||
{formatCredits(blockCost.cost_amount)}
|
||||
</Text>
|
||||
<Text variant="small">
|
||||
|
||||
@@ -42,7 +42,7 @@ export const NodeHeader = ({ data, nodeId }: Props) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-auto flex-col gap-1 rounded-xlarge border-b border-zinc-200 bg-linear-to-r from-slate-50/80 to-white/90 px-4 py-4 pt-3">
|
||||
<div className="flex h-auto flex-col gap-1 rounded-xlarge border-b border-zinc-200 bg-gradient-to-r from-slate-50/80 to-white/90 px-4 py-4 pt-3">
|
||||
{/* Title row with context menu */}
|
||||
<div className="flex items-start justify-between gap-2">
|
||||
<div className="flex min-w-0 flex-1 items-center gap-2">
|
||||
@@ -57,8 +57,8 @@ export const NodeHeader = ({ data, nodeId }: Props) => {
|
||||
onChange={(e) => setEditedTitle(e.target.value)}
|
||||
autoFocus
|
||||
className={cn(
|
||||
"m-0 h-fit w-full border-none bg-transparent p-0 focus:ring-0 focus:outline-hidden",
|
||||
"font-sans text-[1rem] leading-6 font-semibold text-zinc-800",
|
||||
"m-0 h-fit w-full border-none bg-transparent p-0 focus:outline-none focus:ring-0",
|
||||
"font-sans text-[1rem] font-semibold leading-[1.5rem] text-zinc-800",
|
||||
)}
|
||||
onBlur={handleTitleEdit}
|
||||
onKeyDown={handleTitleKeyDown}
|
||||
@@ -87,7 +87,7 @@ export const NodeHeader = ({ data, nodeId }: Props) => {
|
||||
<div className="flex items-center gap-2">
|
||||
<Text
|
||||
variant="small"
|
||||
className="shrink-0 font-medium! text-slate-500!"
|
||||
className="shrink-0 !font-medium !text-slate-500"
|
||||
>
|
||||
#{nodeId.split("-")[0]}
|
||||
</Text>
|
||||
|
||||
@@ -36,7 +36,7 @@ export const NodeDataRenderer = ({ nodeId }: { nodeId: string }) => {
|
||||
<AccordionTrigger className="py-2 hover:no-underline">
|
||||
<Text
|
||||
variant="body-medium"
|
||||
className="font-semibold! text-slate-700"
|
||||
className="!font-semibold text-slate-700"
|
||||
>
|
||||
Node Output
|
||||
</Text>
|
||||
@@ -82,7 +82,7 @@ export const NodeDataRenderer = ({ nodeId }: { nodeId: string }) => {
|
||||
<div className="flex items-center gap-2">
|
||||
<Text
|
||||
variant="small-medium"
|
||||
className="font-semibold! text-slate-600"
|
||||
className="!font-semibold text-slate-600"
|
||||
>
|
||||
Pin:
|
||||
</Text>
|
||||
@@ -93,7 +93,7 @@ export const NodeDataRenderer = ({ nodeId }: { nodeId: string }) => {
|
||||
<div className="w-full space-y-2">
|
||||
<Text
|
||||
variant="small"
|
||||
className="font-semibold! text-slate-600"
|
||||
className="!font-semibold text-slate-600"
|
||||
>
|
||||
Data:
|
||||
</Text>
|
||||
|
||||
@@ -14,9 +14,7 @@ export const TextRenderer: React.FC<{
|
||||
? text.slice(0, truncateLengthLimit) + "..."
|
||||
: text;
|
||||
|
||||
return (
|
||||
<div className="bg-zinc-50 p-3 text-xs wrap-break-word">{truncated}</div>
|
||||
);
|
||||
return <div className="break-words bg-zinc-50 p-3 text-xs">{truncated}</div>;
|
||||
};
|
||||
|
||||
export const ContentRenderer: React.FC<{
|
||||
@@ -40,14 +38,14 @@ export const ContentRenderer: React.FC<{
|
||||
!shortContent
|
||||
) {
|
||||
return (
|
||||
<div className="overflow-hidden *:rounded-xlarge *:text-xs! [&_pre]:wrap-break-word [&_pre]:whitespace-pre-wrap">
|
||||
<div className="overflow-hidden [&>*]:rounded-xlarge [&>*]:!text-xs [&_pre]:whitespace-pre-wrap [&_pre]:break-words">
|
||||
{renderer?.render(value, metadata)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="overflow-hidden *:rounded-xlarge *:text-xs!">
|
||||
<div className="overflow-hidden [&>*]:rounded-xlarge [&>*]:!text-xs">
|
||||
<TextRenderer value={value} truncateLengthLimit={200} />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -170,7 +170,7 @@ export const NodeDataViewer: FC<NodeDataViewerProps> = ({
|
||||
{groupedExecutions.map((execution) => (
|
||||
<div
|
||||
key={execution.execId}
|
||||
className="rounded-3xl border border-slate-200 bg-white p-4 shadow-xs"
|
||||
className="rounded-3xl border border-slate-200 bg-white p-4 shadow-sm"
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<Text variant="body" className="text-slate-600">
|
||||
|
||||
@@ -56,7 +56,7 @@ export const ViewMoreData = ({
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="small"
|
||||
className="h-fit w-fit min-w-0 text-xs!"
|
||||
className="h-fit w-fit min-w-0 !text-xs"
|
||||
>
|
||||
View More
|
||||
</Button>
|
||||
@@ -72,7 +72,7 @@ export const ViewMoreData = ({
|
||||
{reversedExecutionResults.map((result) => (
|
||||
<div
|
||||
key={result.node_exec_id}
|
||||
className="rounded-3xl border border-slate-200 bg-white p-4 shadow-xs"
|
||||
className="rounded-3xl border border-slate-200 bg-white p-4 shadow-sm"
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<Text variant="body" className="text-slate-600">
|
||||
@@ -103,7 +103,7 @@ export const ViewMoreData = ({
|
||||
<div className="flex items-center gap-2">
|
||||
<Text
|
||||
variant="body-medium"
|
||||
className="font-semibold! text-slate-600"
|
||||
className="!font-semibold text-slate-600"
|
||||
>
|
||||
Pin:
|
||||
</Text>
|
||||
@@ -117,7 +117,7 @@ export const ViewMoreData = ({
|
||||
<div className="w-full space-y-2">
|
||||
<Text
|
||||
variant="body-medium"
|
||||
className="font-semibold! text-slate-600"
|
||||
className="!font-semibold text-slate-600"
|
||||
>
|
||||
Data:
|
||||
</Text>
|
||||
|
||||
@@ -104,7 +104,7 @@ function SubAgentUpdateAvailableBar({
|
||||
</div>
|
||||
<Button
|
||||
size="small"
|
||||
variant={isCompatible ? "primary" : "outline-solid"}
|
||||
variant={isCompatible ? "primary" : "outline"}
|
||||
onClick={onUpdate}
|
||||
className={cn(
|
||||
"h-7 text-xs",
|
||||
|
||||
@@ -198,7 +198,7 @@ function TwoColumnSection({
|
||||
</li>
|
||||
))
|
||||
) : (
|
||||
<li className="text-sm text-gray-400 italic dark:text-gray-500">
|
||||
<li className="text-sm italic text-gray-400 dark:text-gray-500">
|
||||
None
|
||||
</li>
|
||||
)}
|
||||
@@ -224,7 +224,7 @@ function TwoColumnSection({
|
||||
</li>
|
||||
))
|
||||
) : (
|
||||
<li className="text-sm text-gray-400 italic dark:text-gray-500">
|
||||
<li className="text-sm italic text-gray-400 dark:text-gray-500">
|
||||
None
|
||||
</li>
|
||||
)}
|
||||
|
||||
@@ -50,7 +50,7 @@ export const WebhookDisclaimer = ({ nodeId }: { nodeId: string }) => {
|
||||
</Alert>
|
||||
</div>
|
||||
|
||||
<Text variant="small" className="mb-4 ml-6 text-purple-700!">
|
||||
<Text variant="small" className="mb-4 ml-6 !text-purple-700">
|
||||
Below inputs are only for display purposes and cannot be edited.
|
||||
</Text>
|
||||
</>
|
||||
|
||||
@@ -140,7 +140,7 @@ export const OutputHandler = ({
|
||||
as="span"
|
||||
className={cn(
|
||||
colorClass,
|
||||
isBroken && "text-red-500! line-through",
|
||||
isBroken && "!text-red-500 line-through",
|
||||
)}
|
||||
>
|
||||
({displayType})
|
||||
@@ -180,7 +180,7 @@ export const OutputHandler = ({
|
||||
>
|
||||
<Text
|
||||
variant="body"
|
||||
className="flex items-center gap-2 font-semibold! text-slate-700"
|
||||
className="flex items-center gap-2 !font-semibold text-slate-700"
|
||||
>
|
||||
Output{" "}
|
||||
<CaretDownIcon
|
||||
|
||||
@@ -96,7 +96,7 @@ export const getTypeDisplayInfo = (schema: any) => {
|
||||
) {
|
||||
return {
|
||||
displayType: "table",
|
||||
colorClass: "text-indigo-500!",
|
||||
colorClass: "!text-indigo-500",
|
||||
hexColor: "#6366f1",
|
||||
};
|
||||
}
|
||||
@@ -108,32 +108,32 @@ export const getTypeDisplayInfo = (schema: any) => {
|
||||
> = {
|
||||
file: {
|
||||
displayType: "file",
|
||||
colorClass: "text-green-500!",
|
||||
colorClass: "!text-green-500",
|
||||
hexColor: "#22c55e",
|
||||
},
|
||||
date: {
|
||||
displayType: "date",
|
||||
colorClass: "text-blue-500!",
|
||||
colorClass: "!text-blue-500",
|
||||
hexColor: "#3b82f6",
|
||||
},
|
||||
time: {
|
||||
displayType: "time",
|
||||
colorClass: "text-blue-500!",
|
||||
colorClass: "!text-blue-500",
|
||||
hexColor: "#3b82f6",
|
||||
},
|
||||
"date-time": {
|
||||
displayType: "datetime",
|
||||
colorClass: "text-blue-500!",
|
||||
colorClass: "!text-blue-500",
|
||||
hexColor: "#3b82f6",
|
||||
},
|
||||
"long-text": {
|
||||
displayType: "text",
|
||||
colorClass: "text-green-500!",
|
||||
colorClass: "!text-green-500",
|
||||
hexColor: "#22c55e",
|
||||
},
|
||||
"short-text": {
|
||||
displayType: "text",
|
||||
colorClass: "text-green-500!",
|
||||
colorClass: "!text-green-500",
|
||||
hexColor: "#22c55e",
|
||||
},
|
||||
};
|
||||
@@ -157,14 +157,14 @@ export const getTypeDisplayInfo = (schema: any) => {
|
||||
const displayType = typeMap[schema?.type] || schema?.type || "any";
|
||||
|
||||
const colorMap: Record<string, string> = {
|
||||
string: "text-green-500!",
|
||||
number: "text-blue-500!",
|
||||
integer: "text-blue-500!",
|
||||
boolean: "text-yellow-500!",
|
||||
object: "text-purple-500!",
|
||||
array: "text-indigo-500!",
|
||||
null: "text-gray-500!",
|
||||
any: "text-gray-500!",
|
||||
string: "!text-green-500",
|
||||
number: "!text-blue-500",
|
||||
integer: "!text-blue-500",
|
||||
boolean: "!text-yellow-500",
|
||||
object: "!text-purple-500",
|
||||
array: "!text-indigo-500",
|
||||
null: "!text-gray-500",
|
||||
any: "!text-gray-500",
|
||||
};
|
||||
|
||||
const hexColorMap: Record<string, string> = {
|
||||
@@ -178,7 +178,7 @@ export const getTypeDisplayInfo = (schema: any) => {
|
||||
any: "#6b7280",
|
||||
};
|
||||
|
||||
const colorClass = colorMap[schema?.type] || "text-gray-500!";
|
||||
const colorClass = colorMap[schema?.type] || "!text-gray-500";
|
||||
const hexColor = hexColorMap[schema?.type] || "#6b7280";
|
||||
|
||||
return {
|
||||
|
||||
@@ -75,7 +75,7 @@ export const getSecondCalculatorNode = () => {
|
||||
export const getFormContainerSelector = (blockId: string): string | null => {
|
||||
const node = getNodeByBlockId(blockId);
|
||||
if (node) {
|
||||
return `[data-id="form-creator-container-${node.id}"]`;
|
||||
return `[data-id="form-creator-container-${node.id}-node"]`;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -16,9 +16,9 @@ export const createBlockBasicsSteps = (tour: any): StepOptions[] => [
|
||||
id: "focus-new-block",
|
||||
title: "Your First Block!",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">Excellent! This is your <strong>Calculator Block</strong>.</p>
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0" style="margin-top: 0.5rem;">Let's explore how blocks work.</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">Excellent! This is your <strong>Calculator Block</strong>.</p>
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0" style="margin-top: 0.5rem;">Let's explore how blocks work.</p>
|
||||
</div>
|
||||
`,
|
||||
attachTo: {
|
||||
@@ -54,9 +54,9 @@ export const createBlockBasicsSteps = (tour: any): StepOptions[] => [
|
||||
id: "input-handles",
|
||||
title: "Input Handles",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">On the <strong>left side</strong> of the block are <strong>input handles</strong>.</p>
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0" style="margin-top: 0.5rem;">These are where data flows <em>into</em> the block from other blocks.</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">On the <strong>left side</strong> of the block are <strong>input handles</strong>.</p>
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0" style="margin-top: 0.5rem;">These are where data flows <em>into</em> the block from other blocks.</p>
|
||||
</div>
|
||||
`,
|
||||
attachTo: {
|
||||
@@ -85,9 +85,9 @@ export const createBlockBasicsSteps = (tour: any): StepOptions[] => [
|
||||
id: "output-handles",
|
||||
title: "Output Handles",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">On the <strong>right side</strong> is the <strong>output handle</strong>.</p>
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0" style="margin-top: 0.5rem;">This is where the result flows <em>out</em> to connect to other blocks.</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">On the <strong>right side</strong> is the <strong>output handle</strong>.</p>
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0" style="margin-top: 0.5rem;">This is where the result flows <em>out</em> to connect to other blocks.</p>
|
||||
${banner(ICONS.Drag, "You can drag from output to input handler to connect blocks", "info")}
|
||||
</div>
|
||||
`,
|
||||
|
||||
@@ -20,8 +20,8 @@ export const createBlockMenuSteps = (tour: any): StepOptions[] => [
|
||||
id: "open-block-menu",
|
||||
title: "Open the Block Menu",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">Let's start by opening the Block Menu.</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">Let's start by opening the Block Menu.</p>
|
||||
${banner(ICONS.ClickIcon, "Click this button to open the menu", "action")}
|
||||
</div>
|
||||
`,
|
||||
@@ -48,9 +48,9 @@ export const createBlockMenuSteps = (tour: any): StepOptions[] => [
|
||||
id: "block-menu-overview",
|
||||
title: "The Block Menu",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">This is the <strong>Block Menu</strong> — your toolbox for building agents.</p>
|
||||
<p class="text-sm font-medium leading-5.5 text-zinc-800 m-0" style="margin-top: 0.5rem;">Here you'll find:</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">This is the <strong>Block Menu</strong> — your toolbox for building agents.</p>
|
||||
<p class="text-sm font-medium leading-[1.375rem] text-zinc-800 m-0" style="margin-top: 0.5rem;">Here you'll find:</p>
|
||||
<ul>
|
||||
<li><strong>Input Blocks</strong> — Entry points for data</li>
|
||||
<li><strong>Action Blocks</strong> — Processing and AI operations</li>
|
||||
@@ -81,10 +81,10 @@ export const createBlockMenuSteps = (tour: any): StepOptions[] => [
|
||||
id: "search-calculator",
|
||||
title: "Search for a Block",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">Let's add a Calculator block to start.</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">Let's add a Calculator block to start.</p>
|
||||
${banner(ICONS.Keyboard, "Type Calculator in the search bar", "action")}
|
||||
<p class="text-xs font-normal leading-4.5 text-zinc-500 m-0" style="margin-top: 0.5rem;">The search will filter blocks as you type.</p>
|
||||
<p class="text-xs font-normal leading-[1.125rem] text-zinc-500 m-0" style="margin-top: 0.5rem;">The search will filter blocks as you type.</p>
|
||||
</div>
|
||||
`,
|
||||
attachTo: {
|
||||
@@ -142,12 +142,12 @@ export const createBlockMenuSteps = (tour: any): StepOptions[] => [
|
||||
id: "select-calculator",
|
||||
title: "Add the Calculator Block",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">You should see the <strong>Calculator</strong> block in the results.</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">You should see the <strong>Calculator</strong> block in the results.</p>
|
||||
${banner(ICONS.ClickIcon, "Click on the Calculator block to add it", "action")}
|
||||
|
||||
<div class="bg-zinc-100 ring-1 ring-zinc-200 rounded-2xl p-2 px-4 mt-2 flex items-start gap-2 text-sm font-medium text-zinc-600">
|
||||
<span class="shrink-0">${ICONS.Drag}</span>
|
||||
<span class="flex-shrink-0">${ICONS.Drag}</span>
|
||||
<span>You can also drag blocks onto the canvas</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,8 +5,8 @@ export const createCompletionSteps = (tour: any): StepOptions[] => [
|
||||
id: "congratulations",
|
||||
title: "Congratulations! 🎉",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">You have successfully created and run your first agent flow!</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">You have successfully created and run your first agent flow!</p>
|
||||
|
||||
<div class="mt-3 p-3 bg-green-50 ring-1 ring-green-200 rounded-2xl">
|
||||
<p class="text-sm font-medium text-green-600 m-0">You learned how to:</p>
|
||||
@@ -20,7 +20,7 @@ export const createCompletionSteps = (tour: any): StepOptions[] => [
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p class="text-sm font-medium leading-5.5 text-zinc-800 m-0" style="margin-top: 0.75rem;">Happy building! 🚀</p>
|
||||
<p class="text-sm font-medium leading-[1.375rem] text-zinc-800 m-0" style="margin-top: 0.75rem;">Happy building! 🚀</p>
|
||||
</div>
|
||||
`,
|
||||
when: {
|
||||
|
||||
@@ -65,8 +65,8 @@ export const createConfigureCalculatorSteps = (tour: any): StepOptions[] => [
|
||||
id: "enter-values",
|
||||
title: "Enter Values",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">Now let's configure the block with actual values.</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">Now let's configure the block with actual values.</p>
|
||||
${getRequirementsHtml()}
|
||||
${banner(ICONS.ClickIcon, "Fill in all the required fields above", "action")}
|
||||
</div>
|
||||
|
||||
@@ -72,8 +72,8 @@ export const createConnectionSteps = (tour: any): StepOptions[] => {
|
||||
id: "connect-blocks-output",
|
||||
title: "Connect the Blocks: Output",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">Now, let's connect the <strong>Result output</strong> of the first Calculator to the <strong>input (A)</strong> of the second Calculator.</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">Now, let's connect the <strong>Result output</strong> of the first Calculator to the <strong>input (A)</strong> of the second Calculator.</p>
|
||||
|
||||
<div class="mt-3 p-3 bg-blue-50 ring-1 ring-blue-200 rounded-2xl">
|
||||
<p class="text-sm font-medium text-blue-600 m-0 mb-2">Drag from the Result output:</p>
|
||||
@@ -160,8 +160,8 @@ export const createConnectionSteps = (tour: any): StepOptions[] => {
|
||||
id: "connect-blocks-input",
|
||||
title: "Connect the Blocks: Input",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">Now, connect to the <strong>input (A)</strong> of the second Calculator block.</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">Now, connect to the <strong>input (A)</strong> of the second Calculator block.</p>
|
||||
|
||||
<div class="mt-3 p-3 bg-blue-50 ring-1 ring-blue-200 rounded-2xl">
|
||||
<p class="text-sm font-medium text-blue-600 m-0 mb-2">Drop on the A input:</p>
|
||||
@@ -246,8 +246,8 @@ export const createConnectionSteps = (tour: any): StepOptions[] => {
|
||||
id: "connection-complete",
|
||||
title: "Blocks Connected! 🎉",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">Excellent! Your Calculator blocks are now connected:</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">Excellent! Your Calculator blocks are now connected:</p>
|
||||
|
||||
<div class="mt-3 p-3 bg-green-50 ring-1 ring-green-200 rounded-2xl">
|
||||
<div class="flex items-center justify-center gap-2 text-sm font-medium text-green-600">
|
||||
@@ -258,7 +258,7 @@ export const createConnectionSteps = (tour: any): StepOptions[] => {
|
||||
<p class="text-[0.75rem] text-green-500 m-0 mt-2 text-center italic">The result of Calculator 1 flows into Calculator 2's input A</p>
|
||||
</div>
|
||||
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0" style="margin-top: 0.75rem;">Now let's save and run your agent!</p>
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0" style="margin-top: 0.75rem;">Now let's save and run your agent!</p>
|
||||
</div>
|
||||
`,
|
||||
beforeShowPromise: async () => {
|
||||
|
||||
@@ -14,8 +14,8 @@ export const createRunSteps = (tour: any): StepOptions[] => [
|
||||
id: "press-run",
|
||||
title: "Run Your Agent",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">Your agent is saved and ready! Now let's <strong>run it</strong> to see it in action.</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">Your agent is saved and ready! Now let's <strong>run it</strong> to see it in action.</p>
|
||||
${banner(ICONS.ClickIcon, "Click the Run button", "action")}
|
||||
</div>
|
||||
`,
|
||||
@@ -47,8 +47,8 @@ export const createRunSteps = (tour: any): StepOptions[] => [
|
||||
id: "show-output",
|
||||
title: "View the Output",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">Here's the <strong>output</strong> of your block!</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">Here's the <strong>output</strong> of your block!</p>
|
||||
|
||||
<div class="mt-3 p-3 bg-blue-50 ring-1 ring-blue-200 rounded-2xl">
|
||||
<p class="text-sm font-medium text-blue-600 m-0">Latest Output:</p>
|
||||
|
||||
@@ -13,8 +13,8 @@ export const createSaveSteps = (): StepOptions[] => [
|
||||
id: "open-save",
|
||||
title: "Save Your Agent",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">Before running, we need to <strong>save</strong> your agent.</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">Before running, we need to <strong>save</strong> your agent.</p>
|
||||
${banner(ICONS.ClickIcon, "Click the Save button", "action")}
|
||||
</div>
|
||||
`,
|
||||
@@ -43,10 +43,10 @@ export const createSaveSteps = (): StepOptions[] => [
|
||||
id: "save-details",
|
||||
title: "Name Your Agent",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">Give your agent a <strong>name</strong> and optional description.</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">Give your agent a <strong>name</strong> and optional description.</p>
|
||||
${banner(ICONS.ClickIcon, 'Enter a name and click "Save Agent"', "action")}
|
||||
<p class="text-xs font-normal leading-4.5 text-zinc-500 m-0" style="margin-top: 0.5rem;">Example: "My Calculator Agent"</p>
|
||||
<p class="text-xs font-normal leading-[1.125rem] text-zinc-500 m-0" style="margin-top: 0.5rem;">Example: "My Calculator Agent"</p>
|
||||
</div>
|
||||
`,
|
||||
attachTo: {
|
||||
|
||||
@@ -83,9 +83,9 @@ export const createSecondCalculatorSteps = (tour: any): StepOptions[] => [
|
||||
id: "adding-second-calculator",
|
||||
title: "Adding Second Calculator",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">Great job configuring the first Calculator!</p>
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0" style="margin-top: 0.5rem;">Now let's add a <strong>second Calculator block</strong> and connect them together.</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">Great job configuring the first Calculator!</p>
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0" style="margin-top: 0.5rem;">Now let's add a <strong>second Calculator block</strong> and connect them together.</p>
|
||||
|
||||
<div class="mt-3 p-3 bg-blue-50 ring-1 ring-blue-200 rounded-2xl">
|
||||
<p class="text-sm font-medium text-blue-600 m-0 mb-1">We'll create a chain:</p>
|
||||
@@ -111,9 +111,9 @@ export const createSecondCalculatorSteps = (tour: any): StepOptions[] => [
|
||||
id: "second-calculator-added",
|
||||
title: "Second Calculator Added! ✅",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">I've added a <strong>second Calculator block</strong> to your canvas.</p>
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0" style="margin-top: 0.5rem;">Now let's configure it and connect them together.</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">I've added a <strong>second Calculator block</strong> to your canvas.</p>
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0" style="margin-top: 0.5rem;">Now let's configure it and connect them together.</p>
|
||||
|
||||
<div class="mt-3 p-3 bg-green-50 ring-1 ring-green-200 rounded-2xl">
|
||||
<p class="text-sm font-medium text-green-600 m-0">You now have 2 Calculator blocks!</p>
|
||||
@@ -138,8 +138,8 @@ export const createSecondCalculatorSteps = (tour: any): StepOptions[] => [
|
||||
id: "configure-second-calculator",
|
||||
title: "Configure Second Calculator",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">Now configure the <strong>second Calculator block</strong>.</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">Now configure the <strong>second Calculator block</strong>.</p>
|
||||
${getSecondCalcRequirementsHtml()}
|
||||
${banner(ICONS.ClickIcon, "Fill in field B and select an Operation", "action")}
|
||||
</div>
|
||||
|
||||
@@ -6,16 +6,16 @@ export const createWelcomeSteps = (tour: any): StepOptions[] => [
|
||||
id: "welcome",
|
||||
title: "Welcome to AutoGPT Builder! 👋🏻",
|
||||
text: `
|
||||
<div class="text-sm leading-5.5 text-zinc-800">
|
||||
<p class="text-sm font-normal leading-5.5 text-zinc-800 m-0">This interactive tutorial will teach you how to build your first AI agent.</p>
|
||||
<p class="text-sm font-medium leading-5.5 text-zinc-800 m-0" style="margin-top: 0.75rem;">You'll learn how to:</p>
|
||||
<div class="text-sm leading-[1.375rem] text-zinc-800">
|
||||
<p class="text-sm font-normal leading-[1.375rem] text-zinc-800 m-0">This interactive tutorial will teach you how to build your first AI agent.</p>
|
||||
<p class="text-sm font-medium leading-[1.375rem] text-zinc-800 m-0" style="margin-top: 0.75rem;">You'll learn how to:</p>
|
||||
<ul class="pl-2 text-sm pt-2">
|
||||
<li>- Add blocks to your workflow</li>
|
||||
<li>- Understand block inputs and outputs</li>
|
||||
<li>- Save and run your agent</li>
|
||||
<li>- and much more...</li>
|
||||
</ul>
|
||||
<p class="text-xs font-normal leading-4.5 text-zinc-500 m-0" style="margin-top: 0.75rem;">Estimated time: 3-4 minutes</p>
|
||||
<p class="text-xs font-normal leading-[1.125rem] text-zinc-500 m-0" style="margin-top: 0.75rem;">Estimated time: 3-4 minutes</p>
|
||||
</div>
|
||||
`,
|
||||
buttons: [
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*
|
||||
* Typography (body, small, action, info, tip, warning) uses Tailwind utilities directly in steps.ts
|
||||
*/
|
||||
import "shepherd.js/dist/css/shepherd.css";
|
||||
import "./tutorial.css";
|
||||
|
||||
export const injectTutorialStyles = () => {
|
||||
@@ -60,7 +61,7 @@ export const banner = (
|
||||
const styles = bannerStyles[variant];
|
||||
return `
|
||||
<div class="${styles.bg} ring-1 ${styles.ring} rounded-2xl p-2 px-4 mt-2 flex items-start gap-2 text-sm font-medium ${styles.text} ${className || ""}">
|
||||
<span class="shrink-0">${icon}</span>
|
||||
<span class="flex-shrink-0">${icon}</span>
|
||||
<span>${content}</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
.new-builder-tutorial-disable {
|
||||
opacity: 0.3 !important;
|
||||
pointer-events: none !important;
|
||||
filter: grayscale(100%) !important;
|
||||
}
|
||||
|
||||
.new-builder-tutorial-highlight {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.new-builder-tutorial-highlight * {
|
||||
opacity: 1 !important;
|
||||
filter: none !important;
|
||||
|
||||
@@ -451,7 +451,7 @@ function MCPToolCard({
|
||||
}`}
|
||||
>
|
||||
{/* Header */}
|
||||
<div className="flex items-center gap-2 px-3 pt-3 pb-1">
|
||||
<div className="flex items-center gap-2 px-3 pb-1 pt-3">
|
||||
<span className="flex-1 text-sm font-semibold dark:text-white">
|
||||
{tool.name}
|
||||
</span>
|
||||
|
||||
@@ -24,7 +24,7 @@ export const ControlPanelButton: React.FC<Props> = ({
|
||||
role={as === "div" ? "button" : undefined}
|
||||
disabled={as === "button" ? disabled : undefined}
|
||||
className={cn(
|
||||
"flex w-auto items-center justify-center bg-white px-4 py-4 whitespace-normal text-zinc-800 shadow-none hover:cursor-pointer hover:bg-zinc-100 hover:text-zinc-950 focus:ring-0",
|
||||
"flex w-auto items-center justify-center whitespace-normal bg-white px-4 py-4 text-zinc-800 shadow-none hover:cursor-pointer hover:bg-zinc-100 hover:text-zinc-950 focus:ring-0",
|
||||
selected &&
|
||||
"bg-violet-50 text-violet-700 hover:cursor-default hover:bg-violet-50 hover:text-violet-700 active:bg-violet-50 active:text-violet-700",
|
||||
disabled && "cursor-not-allowed opacity-50 hover:cursor-not-allowed",
|
||||
|
||||
@@ -19,7 +19,7 @@ export const AiBlock: React.FC<Props> = ({
|
||||
return (
|
||||
<Button
|
||||
className={cn(
|
||||
"group flex h-22.5 w-full min-w-30 items-center justify-start space-x-3 rounded-[0.75rem] bg-zinc-50 px-3.5 py-2.5 text-start whitespace-normal shadow-none",
|
||||
"group flex h-[5.625rem] w-full min-w-[7.5rem] items-center justify-start space-x-3 whitespace-normal rounded-[0.75rem] bg-zinc-50 px-[0.875rem] py-[0.625rem] text-start shadow-none",
|
||||
"hover:bg-zinc-100 focus:ring-0 active:bg-zinc-100 active:ring-1 active:ring-zinc-300 disabled:pointer-events-none",
|
||||
className,
|
||||
)}
|
||||
@@ -29,14 +29,14 @@ export const AiBlock: React.FC<Props> = ({
|
||||
<div className="space-y-0.5">
|
||||
<span
|
||||
className={cn(
|
||||
"line-clamp-1 font-sans text-sm leading-5.5 font-medium text-zinc-700 group-disabled:text-zinc-400",
|
||||
"line-clamp-1 font-sans text-sm font-medium leading-[1.375rem] text-zinc-700 group-disabled:text-zinc-400",
|
||||
)}
|
||||
>
|
||||
{title}
|
||||
</span>
|
||||
<span
|
||||
className={cn(
|
||||
"line-clamp-1 font-sans text-xs leading-5 font-normal text-zinc-500 group-disabled:text-zinc-400",
|
||||
"line-clamp-1 font-sans text-xs font-normal leading-5 text-zinc-500 group-disabled:text-zinc-400",
|
||||
)}
|
||||
>
|
||||
{description}
|
||||
@@ -45,7 +45,7 @@ export const AiBlock: React.FC<Props> = ({
|
||||
|
||||
<span
|
||||
className={cn(
|
||||
"rounded-[0.75rem] bg-zinc-200 px-2 font-sans text-xs leading-5 text-zinc-500",
|
||||
"rounded-[0.75rem] bg-zinc-200 px-[0.5rem] font-sans text-xs leading-[1.25rem] text-zinc-500",
|
||||
)}
|
||||
>
|
||||
Supports {ai_name}
|
||||
@@ -53,7 +53,7 @@ export const AiBlock: React.FC<Props> = ({
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
"flex h-7 w-7 items-center justify-center rounded-small bg-zinc-700 group-disabled:bg-zinc-400",
|
||||
"flex h-7 w-7 items-center justify-center rounded-[0.5rem] bg-zinc-700 group-disabled:bg-zinc-400",
|
||||
)}
|
||||
>
|
||||
<Plus className="h-5 w-5 text-zinc-50" strokeWidth={2} />
|
||||
|
||||
@@ -55,15 +55,15 @@ export const AllBlocksContent = () => {
|
||||
<div className={blockMenuContainerStyle}>
|
||||
{categories?.map((category, index) => (
|
||||
<Fragment key={category.name}>
|
||||
{index > 0 && <Separator className="h-px w-full text-zinc-300" />}
|
||||
{index > 0 && <Separator className="h-[1px] w-full text-zinc-300" />}
|
||||
|
||||
{/* Category Section */}
|
||||
<div className="space-y-2.5">
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="font-sans text-sm leading-5.5 font-medium text-zinc-800">
|
||||
<p className="font-sans text-sm font-medium leading-[1.375rem] text-zinc-800">
|
||||
{category.name && beautifyString(category.name)}
|
||||
</p>
|
||||
<span className="rounded-full bg-zinc-100 px-1.5 font-sans text-sm leading-5.5 text-zinc-600">
|
||||
<span className="rounded-full bg-zinc-100 px-[0.375rem] font-sans text-sm leading-[1.375rem] text-zinc-600">
|
||||
{category.total_blocks}
|
||||
</span>
|
||||
</div>
|
||||
@@ -101,7 +101,7 @@ export const AllBlocksContent = () => {
|
||||
{category.total_blocks > category.blocks.length && (
|
||||
<Button
|
||||
variant={"link"}
|
||||
className="px-0 font-sans text-sm leading-5.5 text-zinc-600 underline hover:text-zinc-800"
|
||||
className="px-0 font-sans text-sm leading-[1.375rem] text-zinc-600 underline hover:text-zinc-800"
|
||||
disabled={isLoadingMore(category.name)}
|
||||
onClick={() => handleRefetchBlocks(category.name)}
|
||||
>
|
||||
|
||||
@@ -149,7 +149,7 @@ export const Block: BlockComponent = ({
|
||||
draggable={!isMCPBlock}
|
||||
data-id={blockDataId}
|
||||
className={cn(
|
||||
"group flex h-16 w-full min-w-30 items-center justify-start space-x-3 rounded-[0.75rem] bg-zinc-50 px-3.5 py-2.5 text-start whitespace-normal shadow-none",
|
||||
"group flex h-16 w-full min-w-[7.5rem] items-center justify-start space-x-3 whitespace-normal rounded-[0.75rem] bg-zinc-50 px-[0.875rem] py-[0.625rem] text-start shadow-none",
|
||||
"hover:cursor-default hover:bg-zinc-100 focus:ring-0 active:bg-zinc-100 active:ring-1 active:ring-zinc-300 disabled:cursor-not-allowed",
|
||||
isMCPBlock && "hover:cursor-pointer",
|
||||
className,
|
||||
@@ -162,7 +162,7 @@ export const Block: BlockComponent = ({
|
||||
{title && (
|
||||
<span
|
||||
className={cn(
|
||||
"line-clamp-1 font-sans text-sm leading-5.5 font-medium text-zinc-800 group-disabled:text-zinc-400",
|
||||
"line-clamp-1 font-sans text-sm font-medium leading-[1.375rem] text-zinc-800 group-disabled:text-zinc-400",
|
||||
)}
|
||||
>
|
||||
{highlightText(
|
||||
@@ -174,7 +174,7 @@ export const Block: BlockComponent = ({
|
||||
{description && (
|
||||
<span
|
||||
className={cn(
|
||||
"line-clamp-1 font-sans text-xs leading-5 font-normal text-zinc-500 group-disabled:text-zinc-400",
|
||||
"line-clamp-1 font-sans text-xs font-normal leading-5 text-zinc-500 group-disabled:text-zinc-400",
|
||||
)}
|
||||
>
|
||||
{highlightText(description, highlightedText)}
|
||||
@@ -183,7 +183,7 @@ export const Block: BlockComponent = ({
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
"flex h-7 w-7 items-center justify-center rounded-small bg-zinc-700 group-disabled:bg-zinc-400",
|
||||
"flex h-7 w-7 items-center justify-center rounded-[0.5rem] bg-zinc-700 group-disabled:bg-zinc-400",
|
||||
)}
|
||||
>
|
||||
<PlusIcon className="h-5 w-5 text-zinc-50" />
|
||||
@@ -202,12 +202,12 @@ export const Block: BlockComponent = ({
|
||||
|
||||
const BlockSkeleton = () => {
|
||||
return (
|
||||
<Skeleton className="flex h-16 w-full min-w-30 animate-pulse items-center justify-start space-x-3 rounded-[0.75rem] bg-zinc-100 px-3.5 py-2.5">
|
||||
<Skeleton className="flex h-16 w-full min-w-[7.5rem] animate-pulse items-center justify-start space-x-3 rounded-[0.75rem] bg-zinc-100 px-[0.875rem] py-[0.625rem]">
|
||||
<div className="flex flex-1 flex-col items-start gap-0.5">
|
||||
<Skeleton className="h-5.5 w-24 rounded bg-zinc-200" />
|
||||
<Skeleton className="h-[1.375rem] w-24 rounded bg-zinc-200" />
|
||||
<Skeleton className="h-5 w-32 rounded bg-zinc-200" />
|
||||
</div>
|
||||
<Skeleton className="h-7 w-7 rounded-small bg-zinc-200" />
|
||||
<Skeleton className="h-7 w-7 rounded-[0.5rem] bg-zinc-200" />
|
||||
</Skeleton>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -45,7 +45,7 @@ export const BlockMenu = () => {
|
||||
side="right"
|
||||
align="start"
|
||||
sideOffset={16}
|
||||
className="absolute h-[80vh] w-186.5 overflow-hidden rounded-[1rem] border-none p-0 shadow-[0_2px_6px_0_rgba(0,0,0,0.05)]"
|
||||
className="absolute h-[80vh] w-[46.625rem] overflow-hidden rounded-[1rem] border-none p-0 shadow-[0_2px_6px_0_rgba(0,0,0,0.05)]"
|
||||
data-id="blocks-control-popover-content"
|
||||
>
|
||||
<BlockMenuContent />
|
||||
|
||||
@@ -11,7 +11,7 @@ export const BlockMenuContent = () => {
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col">
|
||||
<BlockMenuSearchBar />
|
||||
<Separator className="h-px w-full text-zinc-300" />
|
||||
<Separator className="h-[1px] w-full text-zinc-300" />
|
||||
{searchQuery ? <BlockMenuSearch /> : <BlockMenuDefault />}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -8,7 +8,7 @@ export const BlockMenuDefault = () => {
|
||||
return (
|
||||
<div className="flex flex-1 overflow-y-auto">
|
||||
<BlockMenuSidebar />
|
||||
<Separator className="h-full w-px text-zinc-300" />
|
||||
<Separator className="h-full w-[1px] text-zinc-300" />
|
||||
<BlockMenuDefaultContent />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -23,7 +23,10 @@ export const BlockMenuSearchBar: React.FC<BlockMenuSearchBarProps> = ({
|
||||
return (
|
||||
<div
|
||||
data-id="blocks-control-search-bar"
|
||||
className={cn("flex min-h-14.25 items-center gap-2.5 px-4", className)}
|
||||
className={cn(
|
||||
"flex min-h-[3.5625rem] items-center gap-2.5 px-4",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<div className="flex h-6 w-6 items-center justify-center">
|
||||
<MagnifyingGlassIcon
|
||||
@@ -41,8 +44,8 @@ export const BlockMenuSearchBar: React.FC<BlockMenuSearchBarProps> = ({
|
||||
}}
|
||||
placeholder={"Blocks, Agents, Integrations or Keywords..."}
|
||||
className={cn(
|
||||
"m-0 border-none p-0 font-sans text-base font-normal text-zinc-800 shadow-none outline-hidden",
|
||||
"placeholder:text-zinc-400 focus:shadow-none focus:ring-0 focus:outline-hidden",
|
||||
"m-0 border-none p-0 font-sans text-base font-normal text-zinc-800 shadow-none outline-none",
|
||||
"placeholder:text-zinc-400 focus:shadow-none focus:outline-none focus:ring-0",
|
||||
)}
|
||||
/>
|
||||
{localQuery.length > 0 && (
|
||||
|
||||
@@ -13,12 +13,12 @@ export const BlockMenuSidebar = () => {
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="w-fit space-y-2 px-4 pt-4">
|
||||
<Skeleton className="h-12 w-51.5" />
|
||||
<Skeleton className="h-12 w-51.5" />
|
||||
<Skeleton className="h-12 w-51.5" />
|
||||
<Skeleton className="h-12 w-51.5" />
|
||||
<Skeleton className="h-12 w-51.5" />
|
||||
<Skeleton className="h-12 w-51.5" />
|
||||
<Skeleton className="h-12 w-[12.875rem]" />
|
||||
<Skeleton className="h-12 w-[12.875rem]" />
|
||||
<Skeleton className="h-12 w-[12.875rem]" />
|
||||
<Skeleton className="h-12 w-[12.875rem]" />
|
||||
<Skeleton className="h-12 w-[12.875rem]" />
|
||||
<Skeleton className="h-12 w-[12.875rem]" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -26,7 +26,7 @@ export const BlockMenuSidebar = () => {
|
||||
return (
|
||||
<div className="w-fit space-y-2 px-4 pt-4">
|
||||
<ErrorCard
|
||||
className="w-51.5"
|
||||
className="w-[12.875rem]"
|
||||
isSuccess={false}
|
||||
responseError={error || undefined}
|
||||
context="block menu"
|
||||
@@ -106,7 +106,7 @@ export const BlockMenuSidebar = () => {
|
||||
onClick={() => setDefaultState(item.type as DefaultStateType)}
|
||||
/>
|
||||
))}
|
||||
<div className="ml-[0.5365rem] space-y-2 border-l border-black/10 pl-3">
|
||||
<div className="ml-[0.5365rem] space-y-2 border-l border-black/10 pl-[0.75rem]">
|
||||
{subMenuItems.map((item) => (
|
||||
<MenuItem
|
||||
key={item.type}
|
||||
|
||||
@@ -25,7 +25,7 @@ export const FilterChip: React.FC<Props> = ({
|
||||
onMouseEnter={() => setIsHovered(true)}
|
||||
onMouseLeave={() => setIsHovered(false)}
|
||||
className={cn(
|
||||
"group w-fit space-x-1 rounded-[1.5rem] border border-zinc-300 bg-transparent px-2.5 py-1.5 shadow-none",
|
||||
"group w-fit space-x-1 rounded-[1.5rem] border border-zinc-300 bg-transparent px-[0.625rem] py-[0.375rem] shadow-none",
|
||||
"hover:border-violet-500 hover:bg-transparent focus:ring-0 disabled:cursor-not-allowed",
|
||||
selected && "border-0 bg-violet-700 hover:border",
|
||||
className,
|
||||
@@ -34,7 +34,7 @@ export const FilterChip: React.FC<Props> = ({
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
"font-sans text-sm leading-5.5 font-medium text-zinc-600 group-hover:text-zinc-600 group-disabled:text-zinc-400",
|
||||
"font-sans text-sm font-medium leading-[1.375rem] text-zinc-600 group-hover:text-zinc-600 group-disabled:text-zinc-400",
|
||||
selected && "text-zinc-50",
|
||||
)}
|
||||
>
|
||||
@@ -57,7 +57,7 @@ export const FilterChip: React.FC<Props> = ({
|
||||
animate={{ opacity: 1, scale: 1, filter: "blur(0px)" }}
|
||||
exit={{ opacity: 0.5, scale: 0.5, filter: "blur(10px)" }}
|
||||
transition={{ duration: 0.3, type: "spring", bounce: 0.2 }}
|
||||
className="flex h-5.5 items-center rounded-xlarge bg-violet-700 p-1.5 text-zinc-50"
|
||||
className="flex h-[1.375rem] items-center rounded-[1.25rem] bg-violet-700 p-[0.375rem] text-zinc-50"
|
||||
>
|
||||
{number > 100 ? "100+" : number}
|
||||
</motion.span>
|
||||
|
||||
@@ -44,7 +44,7 @@ export function FilterSheet({
|
||||
{isOpen && (
|
||||
<motion.div
|
||||
className={cn(
|
||||
"absolute top-2 bottom-2 left-2 z-20 w-3/4 max-w-90 space-y-4 overflow-hidden rounded-[0.75rem] bg-white pb-4 shadow-[0_4px_12px_2px_rgba(0,0,0,0.1)]",
|
||||
"absolute bottom-2 left-2 top-2 z-20 w-3/4 max-w-[22.5rem] space-y-4 overflow-hidden rounded-[0.75rem] bg-white pb-4 shadow-[0_4px_12px_2px_rgba(0,0,0,0.1)]",
|
||||
)}
|
||||
initial={{ x: "-100%", filter: "blur(10px)" }}
|
||||
animate={{ x: 0, filter: "blur(0px)" }}
|
||||
@@ -64,7 +64,7 @@ export function FilterSheet({
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Separator className="h-px w-full text-zinc-300" />
|
||||
<Separator className="h-[1px] w-full text-zinc-300" />
|
||||
|
||||
{/* Category section */}
|
||||
<div className="space-y-4 px-5">
|
||||
@@ -85,7 +85,7 @@ export function FilterSheet({
|
||||
/>
|
||||
<label
|
||||
htmlFor={category.key}
|
||||
className="font-sans text-sm leading-5.5 text-zinc-600"
|
||||
className="font-sans text-sm leading-[1.375rem] text-zinc-600"
|
||||
>
|
||||
{category.name}
|
||||
</label>
|
||||
@@ -110,7 +110,7 @@ export function FilterSheet({
|
||||
/>
|
||||
<label
|
||||
htmlFor={`creator-${creator}`}
|
||||
className="font-sans text-sm leading-5.5 text-zinc-600"
|
||||
className="font-sans text-sm leading-[1.375rem] text-zinc-600"
|
||||
>
|
||||
{creator}
|
||||
</label>
|
||||
@@ -120,7 +120,7 @@ export function FilterSheet({
|
||||
{creators.length > INITIAL_CREATORS_TO_SHOW && (
|
||||
<Button
|
||||
variant={"link"}
|
||||
className="m-0 p-0 font-sans text-sm leading-5.5 font-medium text-zinc-800 underline hover:text-zinc-600"
|
||||
className="m-0 p-0 font-sans text-sm font-medium leading-[1.375rem] text-zinc-800 underline hover:text-zinc-600"
|
||||
onClick={handleToggleShowMoreCreators}
|
||||
>
|
||||
{displayedCreatorsCount < creators.length ? "More" : "Less"}
|
||||
|
||||
@@ -70,21 +70,21 @@ export const HorizontalScroll: React.FC<HorizontalScrollAreaProps> = ({
|
||||
{children}
|
||||
</div>
|
||||
{canScrollLeft && (
|
||||
<div className="pointer-events-none absolute inset-y-0 left-0 w-8 bg-linear-to-r from-background via-background/80 to-background/0" />
|
||||
<div className="pointer-events-none absolute inset-y-0 left-0 w-8 bg-gradient-to-r from-background via-background/80 to-background/0" />
|
||||
)}
|
||||
{canScrollRight && (
|
||||
<div className="pointer-events-none absolute inset-y-0 right-0 w-8 bg-linear-to-l from-background via-background/80 to-background/0" />
|
||||
<div className="pointer-events-none absolute inset-y-0 right-0 w-8 bg-gradient-to-l from-background via-background/80 to-background/0" />
|
||||
)}
|
||||
{canScrollLeft && (
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Scroll left"
|
||||
className="pointer-events-none absolute top-5 left-2 -translate-y-1/2 opacity-0 transition-opacity duration-200 group-hover:pointer-events-auto group-hover:opacity-100"
|
||||
className="pointer-events-none absolute left-2 top-5 -translate-y-1/2 opacity-0 transition-opacity duration-200 group-hover:pointer-events-auto group-hover:opacity-100"
|
||||
onClick={() => scrollByDelta(-scrollAmount)}
|
||||
>
|
||||
<ArrowLeftIcon
|
||||
size={28}
|
||||
className="rounded-full bg-zinc-700 p-1 text-white drop-shadow-sm"
|
||||
className="rounded-full bg-zinc-700 p-1 text-white drop-shadow"
|
||||
weight="light"
|
||||
/>
|
||||
</button>
|
||||
@@ -93,12 +93,12 @@ export const HorizontalScroll: React.FC<HorizontalScrollAreaProps> = ({
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Scroll right"
|
||||
className="pointer-events-none absolute top-5 right-2 -translate-y-1/2 opacity-0 transition-opacity duration-200 group-hover:pointer-events-auto group-hover:opacity-100"
|
||||
className="pointer-events-none absolute right-2 top-5 -translate-y-1/2 opacity-0 transition-opacity duration-200 group-hover:pointer-events-auto group-hover:opacity-100"
|
||||
onClick={() => scrollByDelta(scrollAmount)}
|
||||
>
|
||||
<ArrowRightIcon
|
||||
size={28}
|
||||
className="rounded-full bg-zinc-700 p-1 text-white drop-shadow-sm"
|
||||
className="rounded-full bg-zinc-700 p-1 text-white drop-shadow"
|
||||
weight="light"
|
||||
/>
|
||||
</button>
|
||||
|
||||
@@ -26,20 +26,20 @@ export const Integration: IntegrationComponent = ({
|
||||
return (
|
||||
<Button
|
||||
className={cn(
|
||||
"group flex h-16 w-full min-w-30 items-center justify-start space-x-3 rounded-[0.75rem] bg-zinc-50 px-3.5 py-2.5 text-start whitespace-normal shadow-none",
|
||||
"group flex h-16 w-full min-w-[7.5rem] items-center justify-start space-x-3 whitespace-normal rounded-[0.75rem] bg-zinc-50 px-[0.875rem] py-[0.625rem] text-start shadow-none",
|
||||
"hover:cursor-default hover:bg-zinc-100 focus:ring-0 active:bg-zinc-50 active:ring-1 active:ring-zinc-300 disabled:pointer-events-none",
|
||||
className,
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
<div className="relative h-10.5 w-10.5 overflow-hidden rounded-small bg-white">
|
||||
<div className="relative h-[2.625rem] w-[2.625rem] overflow-hidden rounded-[0.5rem] bg-white">
|
||||
{icon_url && (
|
||||
<Image
|
||||
src={icon_url}
|
||||
alt="integration-icon"
|
||||
fill
|
||||
sizes="2.25rem"
|
||||
className="w-full rounded-small object-contain group-disabled:opacity-50"
|
||||
className="w-full rounded-[0.5rem] object-contain group-disabled:opacity-50"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@@ -47,15 +47,15 @@ export const Integration: IntegrationComponent = ({
|
||||
<div className="w-full">
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
{title && (
|
||||
<p className="line-clamp-1 flex-1 font-sans text-sm leading-5.5 font-medium text-zinc-700 group-disabled:text-zinc-400">
|
||||
<p className="line-clamp-1 flex-1 font-sans text-sm font-medium leading-[1.375rem] text-zinc-700 group-disabled:text-zinc-400">
|
||||
{beautifyString(title)}
|
||||
</p>
|
||||
)}
|
||||
<span className="flex h-5.5 w-6.75 items-center justify-center rounded-xlarge bg-[#f0f0f0] p-1.5 font-sans text-sm leading-5.5 text-zinc-500 group-disabled:text-zinc-400">
|
||||
<span className="flex h-[1.375rem] w-[1.6875rem] items-center justify-center rounded-[1.25rem] bg-[#f0f0f0] p-1.5 font-sans text-sm leading-[1.375rem] text-zinc-500 group-disabled:text-zinc-400">
|
||||
{number_of_blocks}
|
||||
</span>
|
||||
</div>
|
||||
<span className="line-clamp-1 font-sans text-xs leading-5 font-normal text-zinc-500 group-disabled:text-zinc-400">
|
||||
<span className="line-clamp-1 font-sans text-xs font-normal leading-5 text-zinc-500 group-disabled:text-zinc-400">
|
||||
{description}
|
||||
</span>
|
||||
</div>
|
||||
@@ -69,15 +69,15 @@ const IntegrationSkeleton: React.FC<{ className?: string }> = ({
|
||||
return (
|
||||
<Skeleton
|
||||
className={cn(
|
||||
"flex h-16 w-full min-w-30 animate-pulse items-center justify-start space-x-3 rounded-[0.75rem] bg-zinc-100 px-3.5 py-2.5",
|
||||
"flex h-16 w-full min-w-[7.5rem] animate-pulse items-center justify-start space-x-3 rounded-[0.75rem] bg-zinc-100 px-[0.875rem] py-[0.625rem]",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<Skeleton className="h-10.5 w-10.5 rounded-small bg-zinc-200" />
|
||||
<Skeleton className="h-[2.625rem] w-[2.625rem] rounded-[0.5rem] bg-zinc-200" />
|
||||
<div className="flex flex-1 flex-col items-start gap-0.5">
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<Skeleton className="h-5.5 w-24 rounded bg-zinc-200" />
|
||||
<Skeleton className="h-5.5 w-6.75 rounded-xlarge bg-zinc-200" />
|
||||
<Skeleton className="h-[1.375rem] w-24 rounded bg-zinc-200" />
|
||||
<Skeleton className="h-[1.375rem] w-[1.6875rem] rounded-[1.25rem] bg-zinc-200" />
|
||||
</div>
|
||||
<Skeleton className="h-5 w-[80%] rounded bg-zinc-200" />
|
||||
</div>
|
||||
|
||||
@@ -27,7 +27,7 @@ export const IntegrationBlocks = () => {
|
||||
{Array.from({ length: 3 }).map((_, blockIndex) => (
|
||||
<Fragment key={blockIndex}>
|
||||
{blockIndex > 0 && (
|
||||
<Skeleton className="my-4 h-px w-full text-zinc-100" />
|
||||
<Skeleton className="my-4 h-[1px] w-full text-zinc-100" />
|
||||
)}
|
||||
{[0, 1, 2].map((index) => (
|
||||
<IntegrationBlock.Skeleton key={`${blockIndex}-${index}`} />
|
||||
@@ -67,21 +67,21 @@ export const IntegrationBlocks = () => {
|
||||
<div className="flex items-center gap-1">
|
||||
<Button
|
||||
variant={"link"}
|
||||
className="p-0 font-sans text-sm leading-5.5 font-medium text-zinc-800"
|
||||
className="p-0 font-sans text-sm font-medium leading-[1.375rem] text-zinc-800"
|
||||
onClick={() => {
|
||||
setIntegration(undefined);
|
||||
}}
|
||||
>
|
||||
Integrations
|
||||
</Button>
|
||||
<p className="font-sans text-sm leading-5.5 font-medium text-zinc-800">
|
||||
<p className="font-sans text-sm font-medium leading-[1.375rem] text-zinc-800">
|
||||
/
|
||||
</p>
|
||||
<p className="font-sans text-sm leading-5.5 font-medium text-zinc-800">
|
||||
<p className="font-sans text-sm font-medium leading-[1.375rem] text-zinc-800">
|
||||
{integration}
|
||||
</p>
|
||||
</div>
|
||||
<span className="flex h-5.5 w-6.75 items-center justify-center rounded-xlarge bg-[#f0f0f0] p-1.5 font-sans text-sm leading-5.5 text-zinc-500 group-disabled:text-zinc-400">
|
||||
<span className="flex h-[1.375rem] w-[1.6875rem] items-center justify-center rounded-[1.25rem] bg-[#f0f0f0] p-1.5 font-sans text-sm leading-[1.375rem] text-zinc-500 group-disabled:text-zinc-400">
|
||||
{totalBlocks}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -22,13 +22,13 @@ export const IntegrationChip: IntegrationChipComponent = ({
|
||||
return (
|
||||
<Button
|
||||
className={cn(
|
||||
"flex h-13 w-full min-w-30 justify-start gap-2 rounded-small bg-zinc-50 p-2 pr-3 whitespace-normal shadow-none",
|
||||
"flex h-[3.25rem] w-full min-w-[7.5rem] justify-start gap-2 whitespace-normal rounded-[0.5rem] bg-zinc-50 p-2 pr-3 shadow-none",
|
||||
"hover:cursor-default hover:bg-zinc-100 focus:ring-0 active:bg-zinc-100 active:ring-1 active:ring-zinc-300",
|
||||
className,
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
<div className="relative h-9 w-9 rounded-small bg-transparent">
|
||||
<div className="relative h-9 w-9 rounded-[0.5rem] bg-transparent">
|
||||
{icon_url && (
|
||||
<Image
|
||||
src={icon_url}
|
||||
@@ -40,7 +40,7 @@ export const IntegrationChip: IntegrationChipComponent = ({
|
||||
)}
|
||||
</div>
|
||||
{name && (
|
||||
<span className="truncate font-sans text-sm leading-5.5 font-normal text-zinc-800">
|
||||
<span className="truncate font-sans text-sm font-normal leading-[1.375rem] text-zinc-800">
|
||||
{beautifyString(name)}
|
||||
</span>
|
||||
)}
|
||||
@@ -50,8 +50,8 @@ export const IntegrationChip: IntegrationChipComponent = ({
|
||||
|
||||
const IntegrationChipSkeleton: React.FC = () => {
|
||||
return (
|
||||
<Skeleton className="flex h-13 w-full min-w-30 gap-2 rounded-small bg-zinc-100 p-2 pr-3">
|
||||
<Skeleton className="h-9 w-12 rounded-small bg-zinc-200" />
|
||||
<Skeleton className="flex h-[3.25rem] w-full min-w-[7.5rem] gap-2 rounded-[0.5rem] bg-zinc-100 p-2 pr-3">
|
||||
<Skeleton className="h-9 w-12 rounded-[0.5rem] bg-zinc-200" />
|
||||
<Skeleton className="h-5 w-24 self-center rounded-sm bg-zinc-200" />
|
||||
</Skeleton>
|
||||
);
|
||||
|
||||
@@ -77,7 +77,7 @@ export const IntegrationBlock: IntegrationBlockComponent = ({
|
||||
draggable={true}
|
||||
variant={"ghost"}
|
||||
className={cn(
|
||||
"group flex h-16 w-full min-w-30 items-center justify-start gap-3 rounded-[0.75rem] bg-zinc-50 px-3.5 py-2.5 text-start whitespace-normal shadow-none",
|
||||
"group flex h-16 w-full min-w-[7.5rem] items-center justify-start gap-3 whitespace-normal rounded-[0.75rem] bg-zinc-50 px-[0.875rem] py-[0.625rem] text-start shadow-none",
|
||||
"hover:cursor-default hover:bg-zinc-100 focus:ring-0 active:bg-zinc-100 active:ring-1 active:ring-zinc-300 disabled:cursor-not-allowed",
|
||||
className,
|
||||
)}
|
||||
@@ -85,7 +85,7 @@ export const IntegrationBlock: IntegrationBlockComponent = ({
|
||||
onClick={handleClick}
|
||||
{...rest}
|
||||
>
|
||||
<div className="relative h-10.5 w-10.5 rounded-small bg-white">
|
||||
<div className="relative h-[2.625rem] w-[2.625rem] rounded-[0.5rem] bg-white">
|
||||
{icon_url && (
|
||||
<Image
|
||||
src={icon_url}
|
||||
@@ -100,7 +100,7 @@ export const IntegrationBlock: IntegrationBlockComponent = ({
|
||||
{title && (
|
||||
<span
|
||||
className={cn(
|
||||
"line-clamp-1 font-sans text-sm leading-5.5 font-medium text-zinc-800 group-disabled:text-zinc-400",
|
||||
"line-clamp-1 font-sans text-sm font-medium leading-[1.375rem] text-zinc-800 group-disabled:text-zinc-400",
|
||||
)}
|
||||
>
|
||||
{highlightText(
|
||||
@@ -112,7 +112,7 @@ export const IntegrationBlock: IntegrationBlockComponent = ({
|
||||
{description && (
|
||||
<span
|
||||
className={cn(
|
||||
"line-clamp-1 font-sans text-xs leading-5 font-normal text-zinc-500 group-disabled:text-zinc-400",
|
||||
"line-clamp-1 font-sans text-xs font-normal leading-5 text-zinc-500 group-disabled:text-zinc-400",
|
||||
)}
|
||||
>
|
||||
{highlightText(description, highlightedText)}
|
||||
@@ -121,7 +121,7 @@ export const IntegrationBlock: IntegrationBlockComponent = ({
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
"flex h-7 w-7 items-center justify-center rounded-small bg-zinc-700 group-disabled:bg-zinc-400",
|
||||
"flex h-7 w-7 items-center justify-center rounded-[0.5rem] bg-zinc-700 group-disabled:bg-zinc-400",
|
||||
)}
|
||||
>
|
||||
<Plus className="h-5 w-5 text-zinc-50" strokeWidth={2} />
|
||||
@@ -134,16 +134,16 @@ const IntegrationBlockSkeleton = ({ className }: { className?: string }) => {
|
||||
return (
|
||||
<Skeleton
|
||||
className={cn(
|
||||
"flex h-16 w-full min-w-30 animate-pulse items-center justify-start gap-3 rounded-[0.75rem] bg-zinc-100 px-3.5 py-2.5",
|
||||
"flex h-16 w-full min-w-[7.5rem] animate-pulse items-center justify-start gap-3 rounded-[0.75rem] bg-zinc-100 px-[0.875rem] py-[0.625rem]",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<Skeleton className="h-10.5 w-10.5 rounded-small bg-zinc-200" />
|
||||
<Skeleton className="h-[2.625rem] w-[2.625rem] rounded-[0.5rem] bg-zinc-200" />
|
||||
<div className="flex flex-1 flex-col items-start gap-0.5">
|
||||
<Skeleton className="h-5.5 w-24 rounded bg-zinc-200" />
|
||||
<Skeleton className="h-[1.375rem] w-24 rounded bg-zinc-200" />
|
||||
<Skeleton className="h-5 w-32 rounded bg-zinc-200" />
|
||||
</div>
|
||||
<Skeleton className="h-7 w-7 rounded-small bg-zinc-200" />
|
||||
<Skeleton className="h-7 w-7 rounded-[0.5rem] bg-zinc-200" />
|
||||
</Skeleton>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -39,13 +39,13 @@ export const MarketplaceAgentBlock: MarketplaceAgentBlockComponent = ({
|
||||
return (
|
||||
<Button
|
||||
className={cn(
|
||||
"group flex h-17.5 w-full min-w-30 items-center justify-start gap-3 rounded-[0.75rem] bg-zinc-50 p-2.5 pr-3.5 text-start whitespace-normal shadow-none",
|
||||
"group flex h-[4.375rem] w-full min-w-[7.5rem] items-center justify-start gap-3 whitespace-normal rounded-[0.75rem] bg-zinc-50 p-[0.625rem] pr-[0.875rem] text-start shadow-none",
|
||||
"hover:cursor-default hover:bg-zinc-100 focus:ring-0 active:bg-zinc-100 active:ring-1 active:ring-zinc-300 disabled:pointer-events-none",
|
||||
className,
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
<div className="relative h-12.5 w-22.5 overflow-hidden rounded-[0.375rem] bg-white">
|
||||
<div className="relative h-[3.125rem] w-[5.625rem] overflow-hidden rounded-[0.375rem] bg-white">
|
||||
{image_url && (
|
||||
<Image
|
||||
src={image_url}
|
||||
@@ -60,7 +60,7 @@ export const MarketplaceAgentBlock: MarketplaceAgentBlockComponent = ({
|
||||
{title && (
|
||||
<span
|
||||
className={cn(
|
||||
"line-clamp-1 font-sans text-sm leading-5.5 font-medium text-zinc-800 group-disabled:text-zinc-400",
|
||||
"line-clamp-1 font-sans text-sm font-medium leading-[1.375rem] text-zinc-800 group-disabled:text-zinc-400",
|
||||
)}
|
||||
>
|
||||
{highlightText(title, highlightedText)}
|
||||
@@ -69,7 +69,7 @@ export const MarketplaceAgentBlock: MarketplaceAgentBlockComponent = ({
|
||||
<div className="flex items-center space-x-2.5">
|
||||
<span
|
||||
className={cn(
|
||||
"truncate font-sans text-xs leading-5 font-normal text-zinc-500 group-disabled:text-zinc-400",
|
||||
"truncate font-sans text-xs font-normal leading-5 text-zinc-500 group-disabled:text-zinc-400",
|
||||
)}
|
||||
>
|
||||
By {creator_name}
|
||||
@@ -79,7 +79,7 @@ export const MarketplaceAgentBlock: MarketplaceAgentBlockComponent = ({
|
||||
|
||||
<span
|
||||
className={cn(
|
||||
"truncate font-sans text-xs leading-5 font-normal text-zinc-500 group-disabled:text-zinc-400",
|
||||
"truncate font-sans text-xs font-normal leading-5 text-zinc-500 group-disabled:text-zinc-400",
|
||||
)}
|
||||
>
|
||||
{number_of_runs} runs
|
||||
@@ -102,7 +102,7 @@ export const MarketplaceAgentBlock: MarketplaceAgentBlockComponent = ({
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
"flex h-7 min-w-7 items-center justify-center rounded-small bg-zinc-700 group-disabled:bg-zinc-400",
|
||||
"flex h-7 min-w-7 items-center justify-center rounded-[0.5rem] bg-zinc-700 group-disabled:bg-zinc-400",
|
||||
)}
|
||||
>
|
||||
{!loading ? (
|
||||
@@ -121,20 +121,20 @@ const MarketplaceAgentBlockSkeleton: React.FC<{ className?: string }> = ({
|
||||
return (
|
||||
<Skeleton
|
||||
className={cn(
|
||||
"flex h-17.5 w-full min-w-30 animate-pulse items-center justify-start gap-3 rounded-[0.75rem] bg-zinc-100 p-2.5 pr-3.5",
|
||||
"flex h-[4.375rem] w-full min-w-[7.5rem] animate-pulse items-center justify-start gap-3 rounded-[0.75rem] bg-zinc-100 p-[0.625rem] pr-[0.875rem]",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<Skeleton className="h-12.5 w-22.5 rounded-[0.375rem] bg-zinc-200" />
|
||||
<Skeleton className="h-[3.125rem] w-[5.625rem] rounded-[0.375rem] bg-zinc-200" />
|
||||
<div className="flex flex-1 flex-col items-start gap-0.5">
|
||||
<Skeleton className="h-5.5 w-24 rounded bg-zinc-200" />
|
||||
<Skeleton className="h-[1.375rem] w-24 rounded bg-zinc-200" />
|
||||
<div className="flex items-center gap-1">
|
||||
<Skeleton className="h-5 w-16 rounded bg-zinc-200" />
|
||||
|
||||
<Skeleton className="h-5 w-16 rounded bg-zinc-200" />
|
||||
</div>
|
||||
</div>
|
||||
<Skeleton className="h-7 w-7 rounded-small bg-zinc-200" />
|
||||
<Skeleton className="h-7 w-7 rounded-[0.5rem] bg-zinc-200" />
|
||||
</Skeleton>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -23,18 +23,18 @@ export const MenuItem: React.FC<Props> = ({
|
||||
<Button
|
||||
data-id={menuItemType ? `menu-item-${menuItemType}` : undefined}
|
||||
className={cn(
|
||||
"flex h-9.5 w-51.5 justify-between rounded-small bg-transparent p-2 pl-3 whitespace-normal shadow-none",
|
||||
"flex h-[2.375rem] w-[12.875rem] justify-between whitespace-normal rounded-[0.5rem] bg-transparent p-2 pl-3 shadow-none",
|
||||
"hover:cursor-default hover:bg-zinc-100 focus:ring-0",
|
||||
selected && "bg-zinc-100",
|
||||
className,
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
<span className="truncate font-sans text-sm leading-5.5 font-medium text-zinc-800">
|
||||
<span className="truncate font-sans text-sm font-medium leading-[1.375rem] text-zinc-800">
|
||||
{name}
|
||||
</span>
|
||||
{number !== undefined && (
|
||||
<span className="font-sans text-sm leading-5.5 font-normal text-zinc-600">
|
||||
<span className="font-sans text-sm font-normal leading-[1.375rem] text-zinc-600">
|
||||
{number > 100 ? "100+" : number}
|
||||
</span>
|
||||
)}
|
||||
|
||||
@@ -5,10 +5,10 @@ export const NoSearchResult = () => {
|
||||
<div className="flex h-full w-full flex-col items-center justify-center text-center">
|
||||
<SmileySadIcon size={64} className="mb-10 text-zinc-400" />
|
||||
<div className="space-y-1">
|
||||
<p className="font-sans text-sm leading-5.5 font-medium text-zinc-800">
|
||||
<p className="font-sans text-sm font-medium leading-[1.375rem] text-zinc-800">
|
||||
No match found
|
||||
</p>
|
||||
<p className="font-sans text-sm leading-5.5 font-normal text-zinc-600">
|
||||
<p className="font-sans text-sm font-normal leading-[1.375rem] text-zinc-600">
|
||||
Try adjusting your search terms
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -20,14 +20,14 @@ export const SearchHistoryChip: SearchHistoryChipComponent = ({
|
||||
return (
|
||||
<Button
|
||||
className={cn(
|
||||
"my-px h-9 space-x-1 rounded-[1.5rem] bg-zinc-50 p-1.5 pr-2.5 shadow-none",
|
||||
"my-[1px] h-[2.25rem] space-x-1 rounded-[1.5rem] bg-zinc-50 p-[0.375rem] pr-[0.625rem] shadow-none",
|
||||
"hover:cursor-default hover:bg-zinc-100 focus:ring-0 active:bg-zinc-100 active:ring-1 active:ring-zinc-300",
|
||||
className,
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
<ArrowUpRight className="h-6 w-6 text-zinc-500" strokeWidth={1.25} />
|
||||
<span className="font-sans text-sm leading-5.5 font-normal text-zinc-800">
|
||||
<span className="font-sans text-sm font-normal leading-[1.375rem] text-zinc-800">
|
||||
{content}
|
||||
</span>
|
||||
</Button>
|
||||
@@ -39,7 +39,7 @@ const SearchHistoryChipSkeleton: React.FC<{ className?: string }> = ({
|
||||
}) => {
|
||||
return (
|
||||
<Skeleton
|
||||
className={cn("h-9 w-32 rounded-[1.5rem] bg-zinc-100", className)}
|
||||
className={cn("h-[2.25rem] w-32 rounded-[1.5rem] bg-zinc-100", className)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -40,7 +40,7 @@ export const SuggestionContent = () => {
|
||||
{/* Recent searches */}
|
||||
{hasRecentSearches && (
|
||||
<div className="space-y-2.5 px-4">
|
||||
<p className="font-sans text-sm leading-5.5 font-medium text-zinc-800">
|
||||
<p className="font-sans text-sm font-medium leading-[1.375rem] text-zinc-800">
|
||||
Recent searches
|
||||
</p>
|
||||
<HorizontalScroll
|
||||
@@ -75,7 +75,7 @@ export const SuggestionContent = () => {
|
||||
|
||||
{/* Integrations */}
|
||||
<div className="space-y-2.5 px-4">
|
||||
<p className="font-sans text-sm leading-5.5 font-medium text-zinc-800">
|
||||
<p className="font-sans text-sm font-medium leading-[1.375rem] text-zinc-800">
|
||||
Integrations
|
||||
</p>
|
||||
<div className="grid grid-cols-3 grid-rows-2 gap-2">
|
||||
@@ -103,7 +103,7 @@ export const SuggestionContent = () => {
|
||||
|
||||
{/* Top blocks */}
|
||||
<div className="space-y-2.5 px-4">
|
||||
<p className="font-sans text-sm leading-5.5 font-medium text-zinc-800">
|
||||
<p className="font-sans text-sm font-medium leading-[1.375rem] text-zinc-800">
|
||||
Top blocks
|
||||
</p>
|
||||
<div className="space-y-2">
|
||||
|
||||
@@ -34,14 +34,14 @@ export const UGCAgentBlock: UGCAgentBlockComponent = ({
|
||||
return (
|
||||
<Button
|
||||
className={cn(
|
||||
"group flex h-17.5 w-full min-w-30 items-center justify-start gap-3 rounded-[0.75rem] bg-zinc-50 p-2.5 pr-3.5 text-start whitespace-normal shadow-none",
|
||||
"group flex h-[4.375rem] w-full min-w-[7.5rem] items-center justify-start gap-3 whitespace-normal rounded-[0.75rem] bg-zinc-50 p-[0.625rem] pr-[0.875rem] text-start shadow-none",
|
||||
"hover:cursor-default hover:bg-zinc-100 focus:ring-0 active:bg-zinc-100 active:ring-1 active:ring-zinc-300 disabled:cursor-not-allowed",
|
||||
className,
|
||||
)}
|
||||
{...rest}
|
||||
>
|
||||
{image_url && (
|
||||
<div className="relative h-12.5 w-22.5 overflow-hidden rounded-[0.375rem] bg-white">
|
||||
<div className="relative h-[3.125rem] w-[5.625rem] overflow-hidden rounded-[0.375rem] bg-white">
|
||||
<Image
|
||||
src={image_url}
|
||||
alt="integration-icon"
|
||||
@@ -55,7 +55,7 @@ export const UGCAgentBlock: UGCAgentBlockComponent = ({
|
||||
{title && (
|
||||
<span
|
||||
className={cn(
|
||||
"line-clamp-1 font-sans text-sm leading-5.5 font-medium text-zinc-800 group-disabled:text-zinc-400",
|
||||
"line-clamp-1 font-sans text-sm font-medium leading-[1.375rem] text-zinc-800 group-disabled:text-zinc-400",
|
||||
)}
|
||||
>
|
||||
{highlightText(title, highlightedText)}
|
||||
@@ -65,7 +65,7 @@ export const UGCAgentBlock: UGCAgentBlockComponent = ({
|
||||
{edited_time && (
|
||||
<span
|
||||
className={cn(
|
||||
"line-clamp-1 font-sans text-xs leading-5 font-normal text-zinc-500 group-disabled:text-zinc-400",
|
||||
"line-clamp-1 font-sans text-xs font-normal leading-5 text-zinc-500 group-disabled:text-zinc-400",
|
||||
)}
|
||||
>
|
||||
Edited {formatTimeAgo(edited_time.toISOString())}
|
||||
@@ -76,7 +76,7 @@ export const UGCAgentBlock: UGCAgentBlockComponent = ({
|
||||
|
||||
<span
|
||||
className={cn(
|
||||
"line-clamp-1 font-sans text-xs leading-5 font-normal text-zinc-500 group-disabled:text-zinc-400",
|
||||
"line-clamp-1 font-sans text-xs font-normal leading-5 text-zinc-500 group-disabled:text-zinc-400",
|
||||
)}
|
||||
>
|
||||
Version {version}
|
||||
@@ -84,7 +84,7 @@ export const UGCAgentBlock: UGCAgentBlockComponent = ({
|
||||
|
||||
<span
|
||||
className={cn(
|
||||
"rounded-[0.75rem] bg-zinc-200 px-2 font-sans text-xs leading-5 text-zinc-500",
|
||||
"rounded-[0.75rem] bg-zinc-200 px-[0.5rem] font-sans text-xs leading-[1.25rem] text-zinc-500",
|
||||
)}
|
||||
>
|
||||
Your Agent
|
||||
@@ -93,7 +93,7 @@ export const UGCAgentBlock: UGCAgentBlockComponent = ({
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
"flex h-7 w-7 items-center justify-center rounded-small bg-zinc-700 group-disabled:bg-zinc-400",
|
||||
"flex h-7 w-7 items-center justify-center rounded-[0.5rem] bg-zinc-700 group-disabled:bg-zinc-400",
|
||||
)}
|
||||
>
|
||||
{isLoading ? (
|
||||
@@ -112,19 +112,19 @@ const UGCAgentBlockSkeleton: React.FC<{ className?: string }> = ({
|
||||
return (
|
||||
<Skeleton
|
||||
className={cn(
|
||||
"flex h-17.5 w-full min-w-30 animate-pulse items-center justify-start gap-3 rounded-[0.75rem] bg-zinc-100 p-2.5 pr-3.5",
|
||||
"flex h-[4.375rem] w-full min-w-[7.5rem] animate-pulse items-center justify-start gap-3 rounded-[0.75rem] bg-zinc-100 p-[0.625rem] pr-[0.875rem]",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<Skeleton className="h-12.5 w-22.5 rounded-[0.375rem] bg-zinc-200" />
|
||||
<Skeleton className="h-[3.125rem] w-[5.625rem] rounded-[0.375rem] bg-zinc-200" />
|
||||
<div className="flex flex-1 flex-col items-start gap-0.5">
|
||||
<Skeleton className="h-5.5 w-24 rounded bg-zinc-200" />
|
||||
<Skeleton className="h-[1.375rem] w-24 rounded bg-zinc-200" />
|
||||
<div className="flex items-center gap-1">
|
||||
<Skeleton className="h-5 w-16 rounded bg-zinc-200" />
|
||||
<Skeleton className="h-5 w-16 rounded bg-zinc-200" />
|
||||
</div>
|
||||
</div>
|
||||
<Skeleton className="h-7 w-7 rounded-small bg-zinc-200" />
|
||||
<Skeleton className="h-7 w-7 rounded-[0.5rem] bg-zinc-200" />
|
||||
</Skeleton>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@ export const NewControlPanel = memo(() => {
|
||||
return (
|
||||
<section
|
||||
className={cn(
|
||||
"absolute top-10 left-4 z-10 overflow-hidden rounded-[1rem] border-none bg-white p-0 shadow-[0_1px_5px_0_rgba(0,0,0,0.1)]",
|
||||
"absolute left-4 top-10 z-10 overflow-hidden rounded-[1rem] border-none bg-white p-0 shadow-[0_1px_5px_0_rgba(0,0,0,0.1)]",
|
||||
)}
|
||||
>
|
||||
<div className="flex flex-col items-center justify-center rounded-[1rem] p-0">
|
||||
|
||||
@@ -70,7 +70,7 @@ export const NewSaveControl = () => {
|
||||
data-id="save-control-name-input"
|
||||
data-testid="save-control-name-input"
|
||||
maxLength={100}
|
||||
wrapperClassName="mb-0!"
|
||||
wrapperClassName="!mb-0"
|
||||
{...field}
|
||||
/>
|
||||
)}
|
||||
@@ -88,7 +88,7 @@ export const NewSaveControl = () => {
|
||||
data-id="save-control-description-input"
|
||||
data-testid="save-control-description-input"
|
||||
maxLength={500}
|
||||
wrapperClassName="mb-0!"
|
||||
wrapperClassName="!mb-0"
|
||||
{...field}
|
||||
/>
|
||||
)}
|
||||
@@ -104,7 +104,7 @@ export const NewSaveControl = () => {
|
||||
data-testid="save-control-version-output"
|
||||
data-tutorial-id="save-control-version-output"
|
||||
label="Version"
|
||||
wrapperClassName="mb-0!"
|
||||
wrapperClassName="!mb-0"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -58,7 +58,7 @@ export const GraphSearchMenu: React.FC<GraphSearchMenuProps> = ({
|
||||
side="right"
|
||||
align="start"
|
||||
sideOffset={16}
|
||||
className="absolute h-[75vh] w-186.5 overflow-hidden rounded-[1rem] border-none p-0 shadow-[0_2px_6px_0_rgba(0,0,0,0.05)]"
|
||||
className="absolute h-[75vh] w-[46.625rem] overflow-hidden rounded-[1rem] border-none p-0 shadow-[0_2px_6px_0_rgba(0,0,0,0.05)]"
|
||||
data-id="graph-search-popover-content"
|
||||
>
|
||||
<GraphSearchContent
|
||||
|
||||
@@ -48,7 +48,7 @@ export const GraphSearchContent: React.FC<GraphSearchContentProps> = ({
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
|
||||
<Separator className="h-px w-full text-zinc-300" />
|
||||
<Separator className="h-[1px] w-full text-zinc-300" />
|
||||
|
||||
{/* Search Results */}
|
||||
<div className="flex-1 overflow-hidden">
|
||||
@@ -88,7 +88,7 @@ export const GraphSearchContent: React.FC<GraphSearchContentProps> = ({
|
||||
className={`mx-4 my-2 flex h-20 cursor-pointer rounded-lg border border-zinc-200 bg-white ${
|
||||
index === selectedIndex
|
||||
? "border-zinc-400 shadow-md"
|
||||
: "hover:border-zinc-300 hover:shadow-xs"
|
||||
: "hover:border-zinc-300 hover:shadow-sm"
|
||||
}`}
|
||||
onClick={() => onNodeSelect(node.id)}
|
||||
onMouseEnter={() => {
|
||||
@@ -114,7 +114,7 @@ export const GraphSearchContent: React.FC<GraphSearchContentProps> = ({
|
||||
truncateLengthLimit={45}
|
||||
/>
|
||||
</span>
|
||||
<span className="block text-xs font-normal break-all text-zinc-500">
|
||||
<span className="block break-all text-xs font-normal text-zinc-500">
|
||||
<TextRenderer
|
||||
value={
|
||||
getNodeInputOutputSummary(node) ||
|
||||
|
||||
@@ -24,7 +24,10 @@ export const GraphMenuSearchBar: React.FC<GraphMenuSearchBarProps> = ({
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn("flex min-h-14.25 items-center gap-2.5 px-4", className)}
|
||||
className={cn(
|
||||
"flex min-h-[3.5625rem] items-center gap-2.5 px-4",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<div className="flex h-6 w-6 items-center justify-center">
|
||||
<MagnifyingGlassIcon
|
||||
@@ -40,8 +43,8 @@ export const GraphMenuSearchBar: React.FC<GraphMenuSearchBarProps> = ({
|
||||
onKeyDown={onKeyDown}
|
||||
placeholder={"Search your graph for nodes, inputs, outputs..."}
|
||||
className={cn(
|
||||
"m-0 border-none p-0 font-sans text-base font-normal text-zinc-800 shadow-none outline-hidden",
|
||||
"placeholder:text-zinc-400 focus:shadow-none focus:ring-0 focus:outline-hidden",
|
||||
"m-0 border-none p-0 font-sans text-base font-normal text-zinc-800 shadow-none outline-none",
|
||||
"placeholder:text-zinc-400 focus:shadow-none focus:outline-none focus:ring-0",
|
||||
)}
|
||||
autoFocus
|
||||
/>
|
||||
|
||||
@@ -623,7 +623,7 @@ export function AgentRunDraftView({
|
||||
: "inactive";
|
||||
|
||||
return (
|
||||
<div className={cn("flex gap-6 agpt-div", className)}>
|
||||
<div className={cn("agpt-div flex gap-6", className)}>
|
||||
<div className="flex min-w-0 flex-1 flex-col gap-4">
|
||||
{graph.trigger_setup_info && agentPreset && (
|
||||
<Card className="agpt-box">
|
||||
@@ -651,7 +651,7 @@ export function AgentRunDraftView({
|
||||
<div className="nodrag mt-5 flex flex-col gap-1">
|
||||
Webhook URL:
|
||||
<div className="flex gap-2 rounded-md bg-gray-50 p-2">
|
||||
<code className="text-sm select-all">
|
||||
<code className="select-all text-sm">
|
||||
{agentPreset.webhook.url}
|
||||
</code>
|
||||
<Button
|
||||
@@ -702,7 +702,7 @@ export function AgentRunDraftView({
|
||||
{/* Setup Instructions */}
|
||||
{graph.instructions && (
|
||||
<div className="flex items-start gap-2 rounded-md border border-violet-200 bg-violet-50 p-3">
|
||||
<InfoIcon className="mt-0.5 h-4 w-4 shrink-0 text-violet-600" />
|
||||
<InfoIcon className="mt-0.5 h-4 w-4 flex-shrink-0 text-violet-600" />
|
||||
<div className="text-sm text-violet-800">
|
||||
<strong>Setup Instructions:</strong>{" "}
|
||||
<span className="whitespace-pre-wrap">
|
||||
|
||||
@@ -15,6 +15,8 @@ import { ChatSidebar } from "./components/ChatSidebar/ChatSidebar";
|
||||
import { DeleteChatDialog } from "./components/DeleteChatDialog/DeleteChatDialog";
|
||||
import { MobileDrawer } from "./components/MobileDrawer/MobileDrawer";
|
||||
import { MobileHeader } from "./components/MobileHeader/MobileHeader";
|
||||
import { NotificationBanner } from "./components/NotificationBanner/NotificationBanner";
|
||||
import { NotificationDialog } from "./components/NotificationDialog/NotificationDialog";
|
||||
import { ScaleLoader } from "./components/ScaleLoader/ScaleLoader";
|
||||
import { useCopilotPage } from "./useCopilotPage";
|
||||
|
||||
@@ -117,6 +119,7 @@ export function CopilotPage() {
|
||||
onDrop={handleDrop}
|
||||
>
|
||||
{isMobile && <MobileHeader onOpenDrawer={handleOpenDrawer} />}
|
||||
<NotificationBanner />
|
||||
{/* Drop overlay */}
|
||||
<div
|
||||
className={cn(
|
||||
@@ -201,6 +204,7 @@ export function CopilotPage() {
|
||||
onCancel={handleCancelDelete}
|
||||
/>
|
||||
)}
|
||||
<NotificationDialog />
|
||||
</SidebarProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ export function AgentSavedCard({
|
||||
agentPageLink,
|
||||
}: Props) {
|
||||
return (
|
||||
<div className="rounded-xl border border-border/60 bg-card p-4 shadow-xs">
|
||||
<div className="rounded-xl border border-border/60 bg-card p-4 shadow-sm">
|
||||
<div className="flex items-baseline gap-2">
|
||||
<Image
|
||||
src={sparklesImg}
|
||||
|
||||
@@ -70,9 +70,9 @@ export const ChatContainer = ({
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
className="relative px-3 pt-2 pb-2"
|
||||
className="relative px-3 pb-2 pt-2"
|
||||
>
|
||||
<div className="pointer-events-none absolute top-[-18px] right-0 left-0 z-10 h-6 bg-linear-to-b from-transparent to-[#f8f8f9]" />
|
||||
<div className="pointer-events-none absolute left-0 right-0 top-[-18px] z-10 h-6 bg-gradient-to-b from-transparent to-[#f8f8f9]" />
|
||||
<ChatInput
|
||||
inputId="chat-input-session"
|
||||
onSend={onSend}
|
||||
|
||||
@@ -16,7 +16,7 @@ export function FileChips({ files, onRemove, isUploading }: Props) {
|
||||
if (files.length === 0) return null;
|
||||
|
||||
return (
|
||||
<div className="flex w-full flex-wrap gap-2 px-3 pt-2 pb-2">
|
||||
<div className="flex w-full flex-wrap gap-2 px-3 pb-2 pt-2">
|
||||
{files.map((file, index) => (
|
||||
<span
|
||||
key={`${file.name}-${file.size}-${index}`}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useCopilotUIStore } from "@/app/(platform)/copilot/store";
|
||||
import { ChangeEvent, FormEvent, useEffect, useState } from "react";
|
||||
|
||||
interface Args {
|
||||
@@ -16,6 +17,16 @@ export function useChatInput({
|
||||
}: Args) {
|
||||
const [value, setValue] = useState("");
|
||||
const [isSending, setIsSending] = useState(false);
|
||||
const { initialPrompt, setInitialPrompt } = useCopilotUIStore();
|
||||
|
||||
useEffect(
|
||||
function consumeInitialPrompt() {
|
||||
if (!initialPrompt) return;
|
||||
setValue((prev) => (prev.length === 0 ? initialPrompt : prev));
|
||||
setInitialPrompt(null);
|
||||
},
|
||||
[initialPrompt, setInitialPrompt],
|
||||
);
|
||||
|
||||
useEffect(
|
||||
function focusOnMount() {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user