mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
## Summary - Add 8 new GitHub blocks: GetRepositoryInfo, ForkRepository, ListCommits, SearchCode, CompareBranches, GetRepositoryTree, MultiFileCommit, MergePullRequest - Split `repo.py` (2094 lines, 19 blocks) into domain-specific modules: `repo.py`, `repo_branches.py`, `repo_files.py`, `commits.py` - Concurrent blob creation via `asyncio.gather()` in MultiFileCommit - URL-encode branch/ref params via `urllib.parse.quote()` for defense-in-depth - Step-level error handling in MultiFileCommit ref update with recovery SHA - Collapse FileOperation CREATE/UPDATE into UPSERT (Git Trees API treats them identically) - Add `ge=1, le=100` constraints on per_page SchemaFields - Preserve URL scheme in `prepare_pr_api_url` - Handle null commit authors gracefully in ListCommits - Add unit tests for `prepare_pr_api_url`, error-path tests for MergePR/MultiFileCommit, FileOperation enum validation tests ## Test plan - [ ] Block tests pass for all 19 GitHub blocks (CI: `test_available_blocks`) - [ ] New test file `test_github_blocks.py` passes (prepare_pr_api_url, error paths, enum) - [ ] `check-docs-sync` passes with regenerated docs - [ ] pyright/ruff clean on all changed files
409 lines
14 KiB
Python
409 lines
14 KiB
Python
import uuid
|
|
from typing import List
|
|
|
|
from backend.blocks._base import BlockOutput, BlockSchemaInput, BlockSchemaOutput
|
|
from backend.data.model import APIKeyCredentials, SchemaField
|
|
from backend.util.settings import BehaveAs, Settings
|
|
|
|
from ._api import (
|
|
TEST_CREDENTIALS,
|
|
TEST_CREDENTIALS_INPUT,
|
|
CustomerDetails,
|
|
OrderItem,
|
|
Slant3DCredentialsField,
|
|
Slant3DCredentialsInput,
|
|
)
|
|
from .base import Slant3DBlockBase
|
|
|
|
settings = Settings()
|
|
|
|
|
|
class Slant3DCreateOrderBlock(Slant3DBlockBase):
|
|
"""Block for creating new orders"""
|
|
|
|
class Input(BlockSchemaInput):
|
|
credentials: Slant3DCredentialsInput = Slant3DCredentialsField()
|
|
order_number: str = SchemaField(
|
|
description="Your custom order number (or leave blank for a random one)",
|
|
default_factory=lambda: str(uuid.uuid4()),
|
|
)
|
|
customer: CustomerDetails = SchemaField(
|
|
description="Customer details for where to ship the item",
|
|
advanced=False,
|
|
)
|
|
items: List[OrderItem] = SchemaField(
|
|
description="List of items to print",
|
|
advanced=False,
|
|
)
|
|
|
|
class Output(BlockSchemaOutput):
|
|
order_id: str = SchemaField(description="Slant3D order ID")
|
|
|
|
def __init__(self):
|
|
super().__init__(
|
|
id="f73007d6-f48f-4aaf-9e6b-6883998a09b4",
|
|
description="Create a new print order",
|
|
input_schema=self.Input,
|
|
output_schema=self.Output,
|
|
test_input={
|
|
"credentials": TEST_CREDENTIALS_INPUT,
|
|
"order_number": "TEST-001",
|
|
"customer": {
|
|
"name": "John Doe",
|
|
"email": "john@example.com",
|
|
"phone": "123-456-7890",
|
|
"address": "123 Test St",
|
|
"city": "Test City",
|
|
"state": "TS",
|
|
"zip": "12345",
|
|
},
|
|
"items": [
|
|
{
|
|
"file_url": "https://example.com/model.stl",
|
|
"quantity": "1",
|
|
"color": "black",
|
|
"profile": "PLA",
|
|
}
|
|
],
|
|
},
|
|
test_credentials=TEST_CREDENTIALS,
|
|
test_output=[("order_id", "314144241")],
|
|
test_mock={
|
|
"_make_request": lambda *args, **kwargs: {"orderId": "314144241"},
|
|
"_convert_to_color": lambda *args, **kwargs: "black",
|
|
},
|
|
is_sensitive_action=True,
|
|
)
|
|
|
|
async def run(
|
|
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
|
|
) -> BlockOutput:
|
|
try:
|
|
order_data = await self._format_order_data(
|
|
input_data.customer,
|
|
input_data.order_number,
|
|
input_data.items,
|
|
credentials.api_key.get_secret_value(),
|
|
)
|
|
result = await self._make_request(
|
|
"POST", "order", credentials.api_key.get_secret_value(), json=order_data
|
|
)
|
|
yield "order_id", result["orderId"]
|
|
except Exception as e:
|
|
yield "error", str(e)
|
|
raise
|
|
|
|
|
|
class Slant3DEstimateOrderBlock(Slant3DBlockBase):
|
|
"""Block for getting order cost estimates"""
|
|
|
|
class Input(BlockSchemaInput):
|
|
credentials: Slant3DCredentialsInput = Slant3DCredentialsField()
|
|
order_number: str = SchemaField(
|
|
description="Your custom order number (or leave blank for a random one)",
|
|
default_factory=lambda: str(uuid.uuid4()),
|
|
)
|
|
customer: CustomerDetails = SchemaField(
|
|
description="Customer details for where to ship the item",
|
|
advanced=False,
|
|
)
|
|
items: List[OrderItem] = SchemaField(
|
|
description="List of items to print",
|
|
advanced=False,
|
|
)
|
|
|
|
class Output(BlockSchemaOutput):
|
|
total_price: float = SchemaField(description="Total price in USD")
|
|
shipping_cost: float = SchemaField(description="Shipping cost")
|
|
printing_cost: float = SchemaField(description="Printing cost")
|
|
|
|
def __init__(self):
|
|
super().__init__(
|
|
id="bf8823d6-b42a-48c7-b558-d7c117f2ae85",
|
|
description="Get order cost estimate",
|
|
input_schema=self.Input,
|
|
output_schema=self.Output,
|
|
test_input={
|
|
"credentials": TEST_CREDENTIALS_INPUT,
|
|
"order_number": "TEST-001",
|
|
"customer": {
|
|
"name": "John Doe",
|
|
"email": "john@example.com",
|
|
"phone": "123-456-7890",
|
|
"address": "123 Test St",
|
|
"city": "Test City",
|
|
"state": "TS",
|
|
"zip": "12345",
|
|
},
|
|
"items": [
|
|
{
|
|
"file_url": "https://example.com/model.stl",
|
|
"quantity": "1",
|
|
"color": "black",
|
|
"profile": "PLA",
|
|
}
|
|
],
|
|
},
|
|
test_credentials=TEST_CREDENTIALS,
|
|
test_output=[
|
|
("total_price", 9.31),
|
|
("shipping_cost", 5.56),
|
|
("printing_cost", 3.75),
|
|
],
|
|
test_mock={
|
|
"_make_request": lambda *args, **kwargs: {
|
|
"totalPrice": 9.31,
|
|
"shippingCost": 5.56,
|
|
"printingCost": 3.75,
|
|
},
|
|
"_convert_to_color": lambda *args, **kwargs: "black",
|
|
},
|
|
)
|
|
|
|
async def run(
|
|
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
|
|
) -> BlockOutput:
|
|
order_data = await self._format_order_data(
|
|
input_data.customer,
|
|
input_data.order_number,
|
|
input_data.items,
|
|
credentials.api_key.get_secret_value(),
|
|
)
|
|
result = await self._make_request(
|
|
"POST",
|
|
"order/estimate",
|
|
credentials.api_key.get_secret_value(),
|
|
json=order_data,
|
|
)
|
|
yield "total_price", result["totalPrice"]
|
|
yield "shipping_cost", result["shippingCost"]
|
|
yield "printing_cost", result["printingCost"]
|
|
|
|
|
|
class Slant3DEstimateShippingBlock(Slant3DBlockBase):
|
|
"""Block for getting shipping cost estimates"""
|
|
|
|
class Input(BlockSchemaInput):
|
|
credentials: Slant3DCredentialsInput = Slant3DCredentialsField()
|
|
order_number: str = SchemaField(
|
|
description="Your custom order number (or leave blank for a random one)",
|
|
default_factory=lambda: str(uuid.uuid4()),
|
|
)
|
|
customer: CustomerDetails = SchemaField(
|
|
description="Customer details for where to ship the item"
|
|
)
|
|
items: List[OrderItem] = SchemaField(
|
|
description="List of items to print",
|
|
advanced=False,
|
|
)
|
|
|
|
class Output(BlockSchemaOutput):
|
|
shipping_cost: float = SchemaField(description="Estimated shipping cost")
|
|
currency_code: str = SchemaField(description="Currency code (e.g., 'usd')")
|
|
|
|
def __init__(self):
|
|
super().__init__(
|
|
id="00aae2a1-caf6-4a74-8175-39a0615d44e1",
|
|
description="Get shipping cost estimate",
|
|
input_schema=self.Input,
|
|
output_schema=self.Output,
|
|
test_input={
|
|
"credentials": TEST_CREDENTIALS_INPUT,
|
|
"order_number": "TEST-001",
|
|
"customer": {
|
|
"name": "John Doe",
|
|
"email": "john@example.com",
|
|
"phone": "123-456-7890",
|
|
"address": "123 Test St",
|
|
"city": "Test City",
|
|
"state": "TS",
|
|
"zip": "12345",
|
|
},
|
|
"items": [
|
|
{
|
|
"file_url": "https://example.com/model.stl",
|
|
"quantity": "1",
|
|
"color": "black",
|
|
"profile": "PLA",
|
|
}
|
|
],
|
|
},
|
|
test_credentials=TEST_CREDENTIALS,
|
|
test_output=[("shipping_cost", 4.81), ("currency_code", "usd")],
|
|
test_mock={
|
|
"_make_request": lambda *args, **kwargs: {
|
|
"shippingCost": 4.81,
|
|
"currencyCode": "usd",
|
|
},
|
|
"_convert_to_color": lambda *args, **kwargs: "black",
|
|
},
|
|
)
|
|
|
|
async def run(
|
|
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
|
|
) -> BlockOutput:
|
|
try:
|
|
order_data = await self._format_order_data(
|
|
input_data.customer,
|
|
input_data.order_number,
|
|
input_data.items,
|
|
credentials.api_key.get_secret_value(),
|
|
)
|
|
result = await self._make_request(
|
|
"POST",
|
|
"order/estimateShipping",
|
|
credentials.api_key.get_secret_value(),
|
|
json=order_data,
|
|
)
|
|
yield "shipping_cost", result["shippingCost"]
|
|
yield "currency_code", result["currencyCode"]
|
|
except Exception as e:
|
|
yield "error", str(e)
|
|
raise
|
|
|
|
|
|
class Slant3DGetOrdersBlock(Slant3DBlockBase):
|
|
"""Block for retrieving all orders"""
|
|
|
|
class Input(BlockSchemaInput):
|
|
credentials: Slant3DCredentialsInput = Slant3DCredentialsField()
|
|
|
|
class Output(BlockSchemaOutput):
|
|
orders: List[str] = SchemaField(description="List of orders with their details")
|
|
|
|
def __init__(self):
|
|
super().__init__(
|
|
id="42283bf5-8a32-4fb4-92a2-60a9ea48e105",
|
|
description="Get all orders for the account",
|
|
input_schema=self.Input,
|
|
output_schema=self.Output,
|
|
# This block is disabled for cloud hosted because it allows access to all orders for the account
|
|
disabled=settings.config.behave_as == BehaveAs.CLOUD,
|
|
test_input={"credentials": TEST_CREDENTIALS_INPUT},
|
|
test_credentials=TEST_CREDENTIALS,
|
|
test_output=[
|
|
(
|
|
"orders",
|
|
[
|
|
"1234567890",
|
|
],
|
|
)
|
|
],
|
|
test_mock={
|
|
"_make_request": lambda *args, **kwargs: {
|
|
"ordersData": [
|
|
{
|
|
"orderId": 1234567890,
|
|
"orderTimestamp": {
|
|
"_seconds": 1719510986,
|
|
"_nanoseconds": 710000000,
|
|
},
|
|
}
|
|
]
|
|
}
|
|
},
|
|
)
|
|
|
|
async def run(
|
|
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
|
|
) -> BlockOutput:
|
|
try:
|
|
result = await self._make_request(
|
|
"GET", "order", credentials.api_key.get_secret_value()
|
|
)
|
|
yield "orders", [str(order["orderId"]) for order in result["ordersData"]]
|
|
except Exception as e:
|
|
yield "error", str(e)
|
|
raise
|
|
|
|
|
|
class Slant3DTrackingBlock(Slant3DBlockBase):
|
|
"""Block for tracking order status and shipping"""
|
|
|
|
class Input(BlockSchemaInput):
|
|
credentials: Slant3DCredentialsInput = Slant3DCredentialsField()
|
|
order_id: str = SchemaField(description="Slant3D order ID to track")
|
|
|
|
class Output(BlockSchemaOutput):
|
|
status: str = SchemaField(description="Order status")
|
|
tracking_numbers: List[str] = SchemaField(
|
|
description="List of tracking numbers"
|
|
)
|
|
|
|
def __init__(self):
|
|
super().__init__(
|
|
id="dd7c0293-c5af-4551-ba3e-fc162fb1fb89",
|
|
description="Track order status and shipping",
|
|
input_schema=self.Input,
|
|
output_schema=self.Output,
|
|
test_input={
|
|
"credentials": TEST_CREDENTIALS_INPUT,
|
|
"order_id": "314144241",
|
|
},
|
|
test_credentials=TEST_CREDENTIALS,
|
|
test_output=[("status", "awaiting_shipment"), ("tracking_numbers", [])],
|
|
test_mock={
|
|
"_make_request": lambda *args, **kwargs: {
|
|
"status": "awaiting_shipment",
|
|
"trackingNumbers": [],
|
|
}
|
|
},
|
|
)
|
|
|
|
async def run(
|
|
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
|
|
) -> BlockOutput:
|
|
try:
|
|
result = await self._make_request(
|
|
"GET",
|
|
f"order/{input_data.order_id}/get-tracking",
|
|
credentials.api_key.get_secret_value(),
|
|
)
|
|
yield "status", result["status"]
|
|
yield "tracking_numbers", result["trackingNumbers"]
|
|
except Exception as e:
|
|
yield "error", str(e)
|
|
raise
|
|
|
|
|
|
class Slant3DCancelOrderBlock(Slant3DBlockBase):
|
|
"""Block for canceling orders"""
|
|
|
|
class Input(BlockSchemaInput):
|
|
credentials: Slant3DCredentialsInput = Slant3DCredentialsField()
|
|
order_id: str = SchemaField(description="Slant3D order ID to cancel")
|
|
|
|
class Output(BlockSchemaOutput):
|
|
status: str = SchemaField(description="Cancellation status message")
|
|
|
|
def __init__(self):
|
|
super().__init__(
|
|
id="54de35e1-407f-450b-b5fa-3b5e2eba8185",
|
|
description="Cancel an existing order",
|
|
input_schema=self.Input,
|
|
output_schema=self.Output,
|
|
test_input={
|
|
"credentials": TEST_CREDENTIALS_INPUT,
|
|
"order_id": "314144241",
|
|
},
|
|
test_credentials=TEST_CREDENTIALS,
|
|
test_output=[("status", "Order cancelled")],
|
|
test_mock={
|
|
"_make_request": lambda *args, **kwargs: {"status": "Order cancelled"}
|
|
},
|
|
)
|
|
|
|
async def run(
|
|
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
|
|
) -> BlockOutput:
|
|
try:
|
|
result = await self._make_request(
|
|
"DELETE",
|
|
f"order/{input_data.order_id}",
|
|
credentials.api_key.get_secret_value(),
|
|
)
|
|
yield "status", result["status"]
|
|
except Exception as e:
|
|
yield "error", str(e)
|
|
raise
|