mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
feat(classic): add platform_blocks to Agent, enable via PLATFORM_API_KEY
- Add PlatformBlocksComponent to Agent as a default component - Component automatically enables when PLATFORM_API_KEY env var is set - Config now uses UserConfigurable for env var support: - PLATFORM_API_KEY (required to enable) - PLATFORM_URL (default: https://platform.agpt.co) - PLATFORM_BLOCKS_ENABLED (default: true) - PLATFORM_TIMEOUT (default: 60) - API key stored as SecretStr for security Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -36,24 +36,36 @@ class PlatformBlocksComponent(
|
||||
def client(self) -> PlatformClient:
|
||||
"""Get or create the platform client."""
|
||||
if self._client is None:
|
||||
api_key = ""
|
||||
if self.config.api_key:
|
||||
api_key = self.config.api_key.get_secret_value()
|
||||
self._client = PlatformClient(
|
||||
base_url=self.config.platform_url,
|
||||
api_key=self.config.api_key,
|
||||
api_key=api_key,
|
||||
timeout=self.config.timeout,
|
||||
)
|
||||
return self._client
|
||||
|
||||
@property
|
||||
def is_configured(self) -> bool:
|
||||
"""Check if the component is properly configured with an API key."""
|
||||
return bool(
|
||||
self.config.enabled
|
||||
and self.config.api_key
|
||||
and self.config.api_key.get_secret_value()
|
||||
)
|
||||
|
||||
def get_resources(self) -> Iterator[str]:
|
||||
"""Describe available resources."""
|
||||
if self.config.enabled:
|
||||
if self.is_configured:
|
||||
yield (
|
||||
"Access to platform blocks via search_blocks and execute_block "
|
||||
"commands. Use search_blocks first to discover available blocks."
|
||||
)
|
||||
|
||||
def get_commands(self) -> Iterator[Command]:
|
||||
"""Provide available commands."""
|
||||
if not self.config.enabled:
|
||||
"""Provide available commands only if configured with API key."""
|
||||
if not self.is_configured:
|
||||
return
|
||||
yield self.search_blocks
|
||||
yield self.execute_block
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, SecretStr
|
||||
|
||||
from forge.models.config import UserConfigurable
|
||||
|
||||
|
||||
class PlatformBlocksConfig(BaseModel):
|
||||
"""Configuration for platform blocks integration."""
|
||||
"""Configuration for platform blocks integration.
|
||||
|
||||
enabled: bool = Field(
|
||||
default=True, description="Whether platform blocks are enabled"
|
||||
)
|
||||
platform_url: str = Field(
|
||||
Set PLATFORM_API_KEY environment variable to enable platform blocks.
|
||||
"""
|
||||
|
||||
enabled: bool = UserConfigurable(default=True, from_env="PLATFORM_BLOCKS_ENABLED")
|
||||
platform_url: str = UserConfigurable(
|
||||
default="https://platform.agpt.co",
|
||||
description="Platform API base URL",
|
||||
from_env="PLATFORM_URL",
|
||||
)
|
||||
api_key: str = Field(default="", description="Platform API key for authentication")
|
||||
timeout: int = Field(default=60, description="Request timeout in seconds")
|
||||
api_key: Optional[SecretStr] = UserConfigurable(
|
||||
default=None,
|
||||
from_env="PLATFORM_API_KEY",
|
||||
exclude=True,
|
||||
)
|
||||
timeout: int = UserConfigurable(default=60, from_env="PLATFORM_TIMEOUT")
|
||||
|
||||
@@ -4,6 +4,7 @@ import json
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
import pytest
|
||||
from pydantic import SecretStr
|
||||
|
||||
from forge.components.platform_blocks import (
|
||||
PlatformBlocksComponent,
|
||||
@@ -63,8 +64,10 @@ def mock_blocks_response():
|
||||
|
||||
@pytest.fixture
|
||||
def component():
|
||||
"""Create a PlatformBlocksComponent for testing."""
|
||||
return PlatformBlocksComponent()
|
||||
"""Create a PlatformBlocksComponent for testing with API key configured."""
|
||||
return PlatformBlocksComponent(
|
||||
config=PlatformBlocksConfig(api_key=SecretStr("test-api-key"))
|
||||
)
|
||||
|
||||
|
||||
class TestSearchBlocks:
|
||||
@@ -223,7 +226,7 @@ class TestConfiguration:
|
||||
config = PlatformBlocksConfig()
|
||||
assert config.enabled is True
|
||||
assert config.platform_url == "https://platform.agpt.co"
|
||||
assert config.api_key == ""
|
||||
assert config.api_key is None
|
||||
assert config.timeout == 60
|
||||
|
||||
def test_custom_configuration(self):
|
||||
@@ -231,12 +234,13 @@ class TestConfiguration:
|
||||
config = PlatformBlocksConfig(
|
||||
enabled=False,
|
||||
platform_url="https://dev-builder.agpt.co",
|
||||
api_key="test-key",
|
||||
api_key=SecretStr("test-key"),
|
||||
timeout=120,
|
||||
)
|
||||
assert config.enabled is False
|
||||
assert config.platform_url == "https://dev-builder.agpt.co"
|
||||
assert config.api_key == "test-key"
|
||||
assert config.api_key is not None
|
||||
assert config.api_key.get_secret_value() == "test-key"
|
||||
assert config.timeout == 120
|
||||
|
||||
def test_component_respects_disabled_config(self):
|
||||
@@ -245,6 +249,22 @@ class TestConfiguration:
|
||||
commands = list(component.get_commands())
|
||||
assert len(commands) == 0
|
||||
|
||||
def test_component_disabled_without_api_key(self):
|
||||
"""Component should not yield commands when api_key is not set."""
|
||||
component = PlatformBlocksComponent(
|
||||
config=PlatformBlocksConfig(enabled=True, api_key=None)
|
||||
)
|
||||
commands = list(component.get_commands())
|
||||
assert len(commands) == 0
|
||||
|
||||
def test_component_enabled_with_api_key(self):
|
||||
"""Component should yield commands when api_key is set."""
|
||||
component = PlatformBlocksComponent(
|
||||
config=PlatformBlocksConfig(enabled=True, api_key=SecretStr("test-key"))
|
||||
)
|
||||
commands = list(component.get_commands())
|
||||
assert len(commands) == 2
|
||||
|
||||
|
||||
class TestProtocols:
|
||||
"""Tests for protocol implementations."""
|
||||
|
||||
@@ -36,6 +36,7 @@ from forge.components.git_operations import GitOperationsComponent
|
||||
from forge.components.http_client import HTTPClientComponent
|
||||
from forge.components.image_gen import ImageGeneratorComponent
|
||||
from forge.components.math_utils import MathUtilsComponent
|
||||
from forge.components.platform_blocks import PlatformBlocksComponent
|
||||
from forge.components.system import SystemComponent
|
||||
from forge.components.text_utils import TextUtilsComponent
|
||||
from forge.components.todo import TodoComponent
|
||||
@@ -211,6 +212,8 @@ class Agent(BaseAgent[AnyActionProposal], Configurable[AgentSettings]):
|
||||
self.watchdog = WatchdogComponent(settings.config, settings.history).run_after(
|
||||
ContextComponent
|
||||
)
|
||||
# Platform blocks (enabled only if PLATFORM_API_KEY is set)
|
||||
self.platform_blocks = PlatformBlocksComponent()
|
||||
|
||||
self.event_history = settings.history
|
||||
|
||||
|
||||
Reference in New Issue
Block a user