Compare commits

...

12 Commits

Author SHA1 Message Date
Bently
7f70271b50 Merge branch 'dev' into cursor/OPEN-2666-create-discord-thread-block-7c66 2025-08-28 20:23:58 +01:00
Cursor Agent
ad0ad220a2 Improve Discord thread creation with channel name and server name support
Co-authored-by: bently.lee <bently.lee@agpt.co>
2025-08-28 18:50:42 +00:00
Cursor Agent
e10bcc3e02 Add CreateDiscordThreadBlock for creating Discord threads programmatically
Co-authored-by: bently.lee <bently.lee@agpt.co>
2025-08-28 18:28:58 +00:00
Swifty
82618aede0 Merge remote-tracking branch 'origin/dev' 2025-08-27 11:39:16 +02:00
Swifty
c4483fa6c7 Merge branch 'dev' 2025-08-20 15:22:08 +02:00
Swifty
c2af8c1a6a Reapply "Merge branch 'master' of https://github.com/Significant-Gravitas/AutoGPT into ntindle/secrt-1218-add-ability-to-reject-approved-agents-in-admin-dashboard"
This reverts commit 260dd526c9.
2025-08-20 15:13:46 +02:00
Nicholas Tindle
483c399812 Revert "feat(platform): add ability to reject approved agents in admin dashboard"
This reverts commit 92515b3683.
2025-08-19 00:49:30 -05:00
Nicholas Tindle
260dd526c9 Revert "Merge branch 'master' of https://github.com/Significant-Gravitas/AutoGPT into ntindle/secrt-1218-add-ability-to-reject-approved-agents-in-admin-dashboard"
This reverts commit 105d5dc7e9, reversing
changes made to 92515b3683.
2025-08-19 00:49:10 -05:00
Nicholas Tindle
75a159db01 Revert "style(frontend): format code and improve dialog titles in approve-reject buttons"
This reverts commit 62032e6584.
2025-08-19 00:48:22 -05:00
Nicholas Tindle
62032e6584 style(frontend): format code and improve dialog titles in approve-reject buttons 2025-08-18 23:32:43 -05:00
Nicholas Tindle
105d5dc7e9 Merge branch 'master' of https://github.com/Significant-Gravitas/AutoGPT into ntindle/secrt-1218-add-ability-to-reject-approved-agents-in-admin-dashboard 2025-08-18 22:59:27 -05:00
Nicholas Tindle
92515b3683 feat(platform): add ability to reject approved agents in admin dashboard
- Modified backend review_store_submission to handle rejecting approved agents
- Added logic to update StoreListing when rejecting approved agents
- Updated UI to show "Revoke" button for approved agents
- Only shows approve button for pending agents
- Updates dialog text appropriately for revoking vs rejecting

Fixes SECRT-1218

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-18 10:35:25 -05:00
3 changed files with 247 additions and 1 deletions

View File

@@ -1,6 +1,7 @@
import base64
import io
import mimetypes
from logging import getLogger
from pathlib import Path
from typing import Any
@@ -20,6 +21,8 @@ from ._auth import (
DiscordBotCredentialsInput,
)
logger = getLogger(__name__)
# Keep backward compatibility alias
DiscordCredentials = DiscordBotCredentialsInput
DiscordCredentialsField = DiscordBotCredentialsField
@@ -1138,3 +1141,209 @@ class DiscordChannelInfoBlock(Block):
raise ValueError(f"Login error occurred: {login_err}")
except Exception as e:
raise ValueError(f"An error occurred: {e}")
class CreateDiscordThreadBlock(Block):
class Input(BlockSchema):
credentials: DiscordCredentials = DiscordCredentialsField()
channel_identifier: str = SchemaField(
description="Channel name or channel ID where the thread will be created"
)
thread_name: str = SchemaField(
description="The name of the thread to create (1-100 characters)"
)
thread_type: str = SchemaField(
description="The type of thread to create",
enum=["public", "private"],
default="public"
)
auto_archive_duration: int = SchemaField(
description="Minutes of inactivity before the thread is automatically archived",
enum=[60, 1440, 4320, 10080],
default=1440
)
initial_message: str = SchemaField(
description="The initial message to send in the thread (optional)",
default="",
advanced=True
)
server_name: str = SchemaField(
description="Server name (optional, helps narrow down the channel search)",
default="",
advanced=True
)
class Output(BlockSchema):
status: str = SchemaField(
description="The status of the operation"
)
thread_id: str = SchemaField(
description="The ID of the created thread"
)
thread_name: str = SchemaField(
description="The name of the created thread"
)
channel_id: str = SchemaField(
description="The ID of the channel where the thread was created"
)
server_id: str = SchemaField(
description="The ID of the server where the thread was created"
)
def __init__(self):
super().__init__(
id="c9d5f1a2-7b8e-4c3d-9f2a-1b8e7c3d9f2a",
input_schema=CreateDiscordThreadBlock.Input,
output_schema=CreateDiscordThreadBlock.Output,
description="Creates a new thread in a Discord channel.",
categories={BlockCategory.SOCIAL},
test_input={
"channel_identifier": "general",
"thread_name": "Test Thread",
"thread_type": "public",
"auto_archive_duration": 1440,
"initial_message": "This is the first message in the thread!",
"server_name": "Test Server",
"credentials": TEST_CREDENTIALS_INPUT,
},
test_output=[
("status", "Thread created successfully"),
("thread_id", "123456789012345678"),
("thread_name", "Test Thread"),
("channel_id", "987654321098765432"),
("server_id", "111222333444555666"),
],
test_mock={
"create_thread": lambda *args, **kwargs: {
"status": "Thread created successfully",
"thread_id": "123456789012345678",
"thread_name": "Test Thread",
"channel_id": "987654321098765432",
"server_id": "111222333444555666",
}
},
test_credentials=TEST_CREDENTIALS,
)
async def create_thread(
self,
token: str,
channel_identifier: str,
thread_name: str,
thread_type: str,
auto_archive_duration: int,
initial_message: str,
server_name: str = None
) -> dict:
intents = discord.Intents.default()
intents.guilds = True
intents.messages = True
client = discord.Client(intents=intents)
result = {}
@client.event
async def on_ready():
logger.debug(f"Logged in as {client.user}")
# Find the channel by name or ID
channel = None
# Try to parse as channel ID first
try:
channel_id_int = int(channel_identifier)
try:
channel = await client.fetch_channel(channel_id_int)
except Exception:
pass
except ValueError:
pass
# If not found by ID, search by name
if channel is None:
for guild in client.guilds:
if server_name and guild.name != server_name:
continue
for ch in guild.text_channels:
if ch.name == channel_identifier or str(ch.id) == channel_identifier:
channel = ch
break
if channel:
break
if channel is None:
result["status"] = f"Channel not found: {channel_identifier}"
await client.close()
return
# Verify it's a text channel
if not hasattr(channel, 'create_thread'):
result["status"] = "Channel does not support thread creation"
await client.close()
return
# Verify server name if provided
if server_name and channel.guild.name != server_name:
result["status"] = f"Channel is not in the specified server: {server_name}"
await client.close()
return
# Create the thread
try:
thread_type_value = discord.ChannelType.public_thread if thread_type == "public" else discord.ChannelType.private_thread
thread = await channel.create_thread(
name=thread_name,
type=thread_type_value,
auto_archive_duration=auto_archive_duration
)
result["status"] = "Thread created successfully"
result["thread_id"] = str(thread.id)
result["thread_name"] = thread.name
result["channel_id"] = str(channel.id)
result["server_id"] = str(channel.guild.id)
# Send initial message if provided
if initial_message:
try:
await thread.send(initial_message)
result["status"] = "Thread created successfully with initial message"
except Exception as e:
result["status"] = f"Thread created but failed to send initial message: {str(e)}"
except Exception as e:
result["status"] = f"Failed to create thread: {str(e)}"
await client.close()
await client.start(token)
return result
async def run(
self, input_data: Input, *, credentials: APIKeyCredentials, **kwargs
) -> BlockOutput:
try:
result = await self.create_thread(
token=credentials.api_key.get_secret_value(),
channel_identifier=input_data.channel_identifier,
thread_name=input_data.thread_name,
thread_type=input_data.thread_type,
auto_archive_duration=input_data.auto_archive_duration,
initial_message=input_data.initial_message,
server_name=input_data.server_name if input_data.server_name else None
)
if result.get("status", "").startswith("Failed") or "error" in result.get("status", "").lower():
raise ValueError(result["status"])
yield "status", result["status"]
yield "thread_id", result["thread_id"]
yield "thread_name", result["thread_name"]
yield "channel_id", result["channel_id"]
yield "server_id", result["server_id"]
except discord.errors.LoginFailure as login_err:
raise ValueError(f"Login error occurred: {login_err}")
except Exception as e:
raise ValueError(f"An error occurred: {e}")

View File

@@ -62,6 +62,7 @@ Below is a comprehensive list of all available blocks, categorized by their prim
| [Publish to Medium](medium.md#publish-to-medium) | Publishes content directly to Medium |
| [Read Discord Messages](discord.md#read-discord-messages) | Retrieves messages from Discord channels |
| [Send Discord Message](discord.md#send-discord-message) | Sends messages to Discord channels |
| [Create Discord Thread](discord.md#create-discord-thread) | Creates threads in Discord channels |
## Search and Information Retrieval
| Block Name | Description |

View File

@@ -51,4 +51,40 @@ The block uses a Discord bot to log into a server, locate the specified channel,
| Status | A string indicating the result of the operation (e.g., "Message sent" or "Channel not found") |
### Possible use case
This block could be used as part of an automated notification system. For example, it could send alerts to a Discord channel when certain events occur in another system, such as when a new user signs up or when a critical error is detected.
This block could be used as part of an automated notification system. For example, it could send alerts to a Discord channel when certain events occur in another system, such as when a new user signs up or when a critical error is detected.
---
## Create Discord Thread
### What it is
A block that creates threads in Discord channels using a bot token.
### What it does
This block connects to Discord using a bot token and creates a new thread in a specified channel. It can create both public and private threads with customizable settings.
### How it works
The block uses a Discord bot to authenticate with Discord, find the specified channel, and create a new thread with the provided settings. It can optionally send an initial message to the newly created thread.
### Inputs
| Input | Description |
|-------|-------------|
| Discord Bot Token | A secret token used to authenticate the bot with Discord |
| Channel Identifier | Channel name or channel ID where the thread will be created |
| Thread Name | The name of the thread to create (1-100 characters) |
| Thread Type | The type of thread to create (public or private) |
| Auto Archive Duration | Minutes of inactivity before the thread is automatically archived (60, 1440, 4320, or 10080) |
| Initial Message | An optional initial message to send in the thread |
| Server Name | Server name (optional, helps narrow down the channel search) |
### Outputs
| Output | Description |
|--------|-------------|
| Status | The status of the operation |
| Thread ID | The ID of the created thread |
| Thread Name | The name of the created thread |
| Channel ID | The ID of the channel where the thread was created |
| Server ID | The ID of the server where the thread was created |
### Possible use case
This block could be used to automatically create discussion threads for specific topics, organize conversations around support tickets, or set up dedicated spaces for project collaborations. For example, when a new project is initiated, the system could automatically create a dedicated thread for team discussions.