fix(backend): fix block docs generator name parsing and content preservation

- Use removesuffix("Block") instead of replace("Block", "") to only
  remove the suffix, not all occurrences (fixes "TwitterGetBlockedUsers"
  becoming "TwitterGetedUsers")
- Fix regex patterns to capture until --- separator instead of next
  heading, ensuring manual content between MANUAL markers is preserved

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Nicholas Tindle
2026-01-16 16:37:09 -06:00
parent 03d5f0affb
commit c3654c9431
5 changed files with 44 additions and 44 deletions

View File

@@ -111,8 +111,8 @@ CATEGORY_FILE_MAP = {
def class_name_to_display_name(class_name: str) -> str:
"""Convert BlockClassName to 'Block Class Name'."""
# Remove 'Block' suffix
name = class_name.replace("Block", "")
# Remove 'Block' suffix (only at the end, not all occurrences)
name = class_name.removesuffix("Block")
# Insert space before capitals
name = re.sub(r"([a-z])([A-Z])", r"\1 \2", name)
# Handle consecutive capitals (e.g., 'HTTPRequest' -> 'HTTP Request')
@@ -583,9 +583,9 @@ def write_block_docs(
manual_content = extract_legacy_content(existing_content)
else:
# Extract manual content specific to this block
# Look for content after the block heading
# Match block heading (h1 or h2) and capture until --- separator
block_pattern = (
rf"(?:^|\n)##? {re.escape(block.name)}\s*\n(.*?)(?=\n##? |\Z)"
rf"(?:^|\n)##? {re.escape(block.name)}\s*\n(.*?)(?=\n---|\Z)"
)
block_match = re.search(block_pattern, existing_content, re.DOTALL)
if block_match:
@@ -650,7 +650,7 @@ def check_docs_in_sync(output_dir: Path, blocks: list[BlockDoc]) -> bool:
manual_sections_by_block = {}
for block in file_blocks:
block_pattern = (
rf"(?:^|\n)##? {re.escape(block.name)}\s*\n(.*?)(?=\n##? |\Z)"
rf"(?:^|\n)##? {re.escape(block.name)}\s*\n(.*?)(?=\n---|\Z)"
)
block_match = re.search(block_pattern, existing_content, re.DOTALL)
if block_match:
@@ -672,7 +672,7 @@ def check_docs_in_sync(output_dir: Path, blocks: list[BlockDoc]) -> bool:
# Check if this specific block's section exists and matches
block_pattern = (
rf"(?:^|\n)(##? {re.escape(block.name)}\s*\n.*?)(?=\n##? |\Z)"
rf"(?:^|\n)(##? {re.escape(block.name)}\s*\n.*?)(?=\n---|\Z)"
)
block_match = re.search(block_pattern, existing_content, re.DOTALL)
if not block_match:

View File

@@ -29,6 +29,7 @@ Below is a comprehensive list of all available blocks, categorized by their prim
| [Agent Table Input](basic.md#agent-table-input) | Block for table data input with customizable headers |
| [Agent Time Input](basic.md#agent-time-input) | Block for time input |
| [Agent Toggle Input](basic.md#agent-toggle-input) | Block for boolean toggle input |
| [Block Installation](basic.md#block-installation) | Given a code string, this block allows the verification and installation of a block code into the system |
| [Dictionary Is Empty](basic.md#dictionary-is-empty) | Checks if a dictionary is empty |
| [File Store](basic.md#file-store) | Stores the input file in the temporary directory |
| [Find In Dictionary](basic.md#find-in-dictionary) | A block that looks up a value in a dictionary, list, or object by key or index and returns the corresponding value |
@@ -39,7 +40,6 @@ Below is a comprehensive list of all available blocks, categorized by their prim
| [Get Store Agent Details](system/store_operations.md#get-store-agent-details) | Get detailed information about an agent from the store |
| [Get Weather Information](basic.md#get-weather-information) | Retrieves weather information for a specified location using OpenWeatherMap API |
| [Human In The Loop](basic.md#human-in-the-loop) | Pause execution and wait for human approval or modification of data |
| [Installation](basic.md#installation) | Given a code string, this block allows the verification and installation of a block code into the system |
| [Linear Search Issues](linear/issues.md#linear-search-issues) | Searches for issues on Linear |
| [List Is Empty](basic.md#list-is-empty) | Checks if a list is empty |
| [List Library Agents](system/library_operations.md#list-library-agents) | List all agents in your personal library |
@@ -323,6 +323,7 @@ Below is a comprehensive list of all available blocks, categorized by their prim
| [Twitter Delete Tweet](twitter/manage.md#twitter-delete-tweet) | This block deletes a tweet on Twitter |
| [Twitter Follow List](twitter/list_follows.md#twitter-follow-list) | This block follows a specified Twitter list for the authenticated user |
| [Twitter Follow User](twitter/follows.md#twitter-follow-user) | This block follows a specified Twitter user |
| [Twitter Get Blocked Users](twitter/blocks.md#twitter-get-blocked-users) | This block retrieves a list of users blocked by the authenticating user |
| [Twitter Get Bookmarked Tweets](twitter/bookmark.md#twitter-get-bookmarked-tweets) | This block retrieves bookmarked tweets from Twitter |
| [Twitter Get Followers](twitter/follows.md#twitter-get-followers) | This block retrieves followers of a specified Twitter user |
| [Twitter Get Following](twitter/follows.md#twitter-get-following) | This block retrieves the users that a specified Twitter user is following |
@@ -348,7 +349,6 @@ Below is a comprehensive list of all available blocks, categorized by their prim
| [Twitter Get User Mentions](twitter/timeline.md#twitter-get-user-mentions) | This block retrieves Tweets mentioning a specific user |
| [Twitter Get User Tweets](twitter/timeline.md#twitter-get-user-tweets) | This block retrieves Tweets composed by a single user |
| [Twitter Get Users](twitter/user_lookup.md#twitter-get-users) | This block retrieves information about multiple Twitter users |
| [Twitter Geted Users](twitter/blocks.md#twitter-geted-users) | This block retrieves a list of users blocked by the authenticating user |
| [Twitter Hide Reply](twitter/hide.md#twitter-hide-reply) | This block hides a reply to a tweet |
| [Twitter Like Tweet](twitter/like.md#twitter-like-tweet) | This block likes a tweet |
| [Twitter Mute User](twitter/mutes.md#twitter-mute-user) | This block mutes a specified Twitter user |

View File

@@ -563,6 +563,40 @@ The toggle is ideal for binary choices like enabling features, confirming action
---
## Block Installation
### What it is
Given a code string, this block allows the verification and installation of a block code into the system.
### How it works
<!-- MANUAL: how_it_works -->
This block allows dynamic installation of new block types into the system from Python code. The code is verified for safety and correctness before installation. Once installed, the new block becomes available for use in workflows.
This enables extensibility by allowing custom blocks to be added without modifying the core system, though it requires the code to follow the block specification format.
<!-- END MANUAL -->
### Inputs
| Input | Description | Type | Required |
|-------|-------------|------|----------|
| code | Python code of the block to be installed | str | Yes |
### Outputs
| Output | Description | Type |
|--------|-------------|------|
| error | Error message if the block installation fails | str |
| success | Success message if the block is installed successfully | str |
### Possible use case
<!-- MANUAL: use_case -->
**Custom Integrations**: Install blocks that connect to proprietary or internal APIs not covered by built-in blocks.
**Dynamic Workflows**: Allow administrators to extend workflow capabilities without redeploying the entire system.
**Experimental Features**: Test new block implementations before formally adding them to the block library.
<!-- END MANUAL -->
---
## Dictionary Is Empty
### What it is
@@ -887,40 +921,6 @@ This enables human oversight at critical points in automated workflows, ensuring
---
## Installation
### What it is
Given a code string, this block allows the verification and installation of a block code into the system.
### How it works
<!-- MANUAL: how_it_works -->
This block allows dynamic installation of new block types into the system from Python code. The code is verified for safety and correctness before installation. Once installed, the new block becomes available for use in workflows.
This enables extensibility by allowing custom blocks to be added without modifying the core system, though it requires the code to follow the block specification format.
<!-- END MANUAL -->
### Inputs
| Input | Description | Type | Required |
|-------|-------------|------|----------|
| code | Python code of the block to be installed | str | Yes |
### Outputs
| Output | Description | Type |
|--------|-------------|------|
| error | Error message if the block installation fails | str |
| success | Success message if the block is installed successfully | str |
### Possible use case
<!-- MANUAL: use_case -->
**Custom Integrations**: Install blocks that connect to proprietary or internal APIs not covered by built-in blocks.
**Dynamic Workflows**: Allow administrators to extend workflow capabilities without redeploying the entire system.
**Experimental Features**: Test new block implementations before formally adding them to the block library.
<!-- END MANUAL -->
---
## List Is Empty
### What it is

View File

@@ -547,7 +547,7 @@ The block sends a request to the D-ID API with your specified parameters. It the
|-------|-------------|------|----------|
| script_input | The text input for the script | str | Yes |
| provider | The voice provider to use | "microsoft" \| "elevenlabs" \| "amazon" | No |
| voice_id | The voice ID to use, get list of voices [here](https://docs.agpt.co/server/d_id) | str | No |
| voice_id | The voice ID to use, see [available voice IDs](https://agpt.co/docs/platform/using-ai-services/d_id) | str | No |
| presenter_id | The presenter ID to use | str | No |
| driver_id | The driver ID to use | str | No |
| result_format | The desired result format | "mp4" \| "gif" \| "wav" | No |

View File

@@ -1,4 +1,4 @@
# Twitter Geted Users
# Twitter Get Blocked Users
## What it is
This block retrieves a list of users blocked by the authenticating user.