Skip to content

Commit

Permalink
enhance: support media posts for wordpress tools (#426)
Browse files Browse the repository at this point in the history
* feat: add tools to support media posts for wordpress, includes image/video/audios..etc

* fix:update requirements.txt

* fix: add missing asyncio import. remove GUID from results of  request as its internal info. update tools.gpt prompt

* fix: update tool.gpt prompt to be more explicit about list vs retrieve posts and media

* fix: fix the env variable name for media file path. update tool.gpt to emphasize that agent should confirm content before create post

* fix: encode params of GET requests saftly
  • Loading branch information
tybalex authored Feb 11, 2025
1 parent 80a3fa7 commit 7db1ab6
Show file tree
Hide file tree
Showing 6 changed files with 412 additions and 47 deletions.
4 changes: 2 additions & 2 deletions wordpress/main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from tools import posts, users, site # import to register tools
from tools import posts, users, site, media # import tool registry
from tools.helper import tool_registry, create_session
import json
import sys
Expand All @@ -16,7 +16,7 @@ def main():
json_response = tool_registry.get(command)(client)
print(json.dumps(json_response, indent=4))
except Exception as e:
print(f"Running command: {' '.join(sys.argv)} yielded error: {e}")
print(f"Running command: {' '.join(sys.argv)} failed. Error: {e}")
sys.exit(1)


Expand Down
3 changes: 2 additions & 1 deletion wordpress/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
requests
requests
git+https://github.com/gptscript-ai/py-gptscript.git@0cebee3afa51b8c56006e479a990c262bd693ba6#egg=gptscript
106 changes: 82 additions & 24 deletions wordpress/tool.gpt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Name: Wordpress
Description: Tools for interacting with self-hosted and hosted Wordpress sites that support basic auth. Wordpress.com sites are not supported.
Metadata: bundle: true
Share Tools: List Users, Get User, List Posts, Retrieve Post, Create Post, Update Post, Delete Post, Get Site Settings
Share Tools: List Users, Get User, List Posts, Retrieve Post, Create Post, Update Post, Delete Post, List Media, Upload Media, Update Media, Delete Media, Get Site Settings

---
Name: List Users
Expand All @@ -23,26 +23,26 @@ Param: user_id: the id of the user to get

---
Name: List Posts
Description: List posts in wordpress site
Description: List posts in wordpress site and get basic information of each post. Date to filter posts must be a valid ISO 8601 date string, in the format of YYYY-MM-DDTHH:MM:SS, or YYYY-MM-DDTHH:MM:SS+HH:MM for timezone aware date.
Credential: ./credential
Share Context: Wordpress Context
Param: context: (optional) the context of the posts to list, must be one of: view, embed, edit, default is view
Param: page: (optional) the page number to list, default is 1
Param: per_page: (optional) the number of posts per page to list, default is 10
Param: author_ids: (optional) a list of comma separated author ids, default is None
Param: search_query: (optional) the search query to filter posts, default is None
Param: search_query: (optional) limit results to those matching a string, default is None
Param: statuses: (optional) a comma separated list of statuses to filter posts, default is publish. Valid statuses are: publish, future, draft, pending, private, trash, auto-draft, inherit, request-pending, request-confirmed, request-failed, request-completed
Param: publish_after: (optional) the date and time to filter posts published after, default is None
Param: publish_before: (optional) the date and time to filter posts published before, default is None
Param: modified_after: (optional) the date and time to filter posts modified after, default is None
Param: modified_before: (optional) the date and time to filter posts modified before, default is None
Param: publish_after: (optional) the date to filter posts published after, default is None
Param: publish_before: (optional) the date to filter posts published before, default is None
Param: modified_after: (optional) the date to filter posts modified after, default is None
Param: modified_before: (optional) the date to filter posts modified before, default is None
Param: order: (optional) the order to sort posts, must be one of: asc, desc, default is desc.

#!/usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py ListPosts

---
Name: Retrieve Post
Description: Retrieve a post in wordpress site
Description: Retrieve all the metadata of a post in wordpress site.
Credential: ./credential
Share Context: Wordpress Context
Param: post_id: the id of the post
Expand All @@ -67,15 +67,16 @@ Share Context: Wordpress Context
Param: title: the title of the post
Param: content: the content of the post.
Param: status: (optional) the status of the post, must be one of: publish, future, draft, pending, private, default is draft.
Param: comment_status: (optional) the comment status of the post, must be one of: open, closed. default is open
Param: comment_status: (optional) the comment status of the post, must be one of: open, closed. Default is open
Param: sticky: (optional) whether the post is sticky to the top of the page, default is false
Param: password: (optional) the password of the post, default is None
Param: slug: (optional) the slug of the post, default is None
Param: slug: (optional) An alphanumeric identifier for the post unique to its type. Default is None
Param: date: (optional) the date of the post, default is None. Must be a valid ISO 8601 date string, in the format of YYYY-MM-DDTHH:MM:SS, or YYYY-MM-DDTHH:MM:SS+HH:MM for timezone aware date. If the date is a future date, the post will be scheduled to be published at that time.
Param: format: (optional) the format of the post to create, must be one of: standard, aside, chat, gallery, link, image, quote, status, video, audio. default is standard
Param: author_id: (optional) the id of the author of the post. If not provided, the current user will be used.
Param: featured_media: (optional) the ID of the featured media for the post. Default is None. Get the Id by List Media Tool.
Param: format: (optional) the format of the post to create, must be one of: standard, aside, chat, gallery, link, image, quote, status, video, audio. Default is standard
Param: author_id: (optional) the ID for the author of the post. If not provided, the current user will be used.
Param: excerpt: (optional) the excerpt of the post, default is None
Param: ping_status: (optional) the ping status of the post, must be one of: open, closed. default is open
Param: ping_status: (optional) the ping status of the post, must be one of: open, closed. Default is open

#!/usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py CreatePost

Expand All @@ -84,19 +85,20 @@ Name: Update Post
Description: Update a post in user's Wordpress site. Only the fields that are provided will be updated. Use HTML tags to format the content, for example, <strong>Bold Text</strong> for bold text.
Credential: ./credential
Share Context: Wordpress Context
Param: post_id: the id of the post to update
Param: post_id: (required) the id of the post to update
Param: title: (optional) the title of the post
Param: content: (optional) the content of the post
Param: status: (optional) the status of the post, must be one of: publish, future, draft, pending, private, default is publish
Param: comment_status: (optional) the comment status of the post, must be one of: open, closed, default is open
Param: sticky: (optional) whether the post is sticky to the top of the page, default is false
Param: password: (optional) the password of the post, default is None
Param: slug: (optional) the slug of the post, default is None
Param: date: (optional) the date of the post, default is None. Must be a valid ISO 8601 date string, in the format of YYYY-MM-DDTHH:MM:SS, or YYYY-MM-DDTHH:MM:SS+HH:MM for timezone aware date. If the date is a future date, the post will be scheduled to be published at that time.
Param: format: (optional) the format of the post to create, must be one of: standard, aside, chat, gallery, link, image, quote, status, video, audio. default is standard
Param: author_id: (optional) the id of the author of the post, default is None
Param: excerpt: (optional) the excerpt of the post, default is None
Param: ping_status: (optional) the ping status of the post, must be one of: open, closed, default is open
Param: status: (optional) the status of the post, must be one of: publish, future, draft, pending, private.
Param: comment_status: (optional) the comment status of the post, must be one of: open, closed.
Param: sticky: (optional) whether the post is sticky to the top of the page
Param: password: (optional) the password of the post
Param: slug: (optional) the slug of the post
Param: date: (optional) the date of the post. Must be a valid ISO 8601 date string, in the format of YYYY-MM-DDTHH:MM:SS, or YYYY-MM-DDTHH:MM:SS+HH:MM for timezone aware date. If the date is a future date, the post will be scheduled to be published at that time.
Param: featured_media: (optional) the ID of the featured media for the post. Get the Id by List Media Tool.
Param: format: (optional) the format of the post to create, must be one of: standard, aside, chat, gallery, link, image, quote, status, video, audio.
Param: author_id: (optional) the id of the author of the post
Param: excerpt: (optional) the excerpt of the post
Param: ping_status: (optional) the ping status of the post, must be one of: open, closed

#!/usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py UpdatePost

Expand All @@ -110,6 +112,60 @@ Param: force: (optional) whether to force delete the post, default is false. If

#!/usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py DeletePost


---
Name: Upload Media
Description: Upload a media file(image, video, audio, etc.) in the workspace to user's wordpress site.
Credential: ./credential
Share Context: Wordpress Context
Param: media_file_path: the file path of the media file in the workspace.

#!/usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py UploadMedia


---
Name: Update Media
Description: Use this tool to update the metadata of a media file in user's wordpress site.
Credential: ./credential
Share Context: Wordpress Context
Param: media_id: (required) the id of the media file.
Param: title: (optional) the title to update.
Param: slug: (optional) the slug to update.
Param: author_id: (optional) the author id of the media file.

#!/usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py UpdateMedia


---
Name: List Media
Description: List media files in user's wordpress site and get basic information of each media file. Date to filter media files must be a valid ISO 8601 date string, in the format of YYYY-MM-DDTHH:MM:SS, or YYYY-MM-DDTHH:MM:SS+HH:MM for timezone aware date.
Credential: ./credential
Share Context: Wordpress Context
Param: context: (optional) the context of the media files to list, must be one of: view, embed, edit, default is view.
Param: page: (optional) the page number to list, default is 1
Param: per_page: (optional) the number of media files per page to list, default is 10
Param: media_type: (optional) Default is None. Limit result set to attachments of a particular media type. If provided, must be one of: image, video, text, application, audio.
Param: author_ids: (optional) a list of comma separated author ids, default is None
Param: search_query: (optional) limit results to those matching a string, default is None
Param: publish_after: (optional) the date to filter media files uploaded after, default is None
Param: publish_before: (optional) the date to filter media files uploaded before, default is None
Param: modified_after: (optional) the date to filter media files modified after, default is None
Param: modified_before: (optional) the date to filter media files modified before, default is None
Param: order: (optional) the order to sort media files, must be one of: asc, desc, default is desc

#!/usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py ListMedia


---
Name: Delete Media
Description: Delete a media file in user's wordpress site
Credential: ./credential
Share Context: Wordpress Context
Param: media_id: the id of the media file

#!/usr/bin/env python3 ${GPTSCRIPT_TOOL_DIR}/main.py DeleteMedia


---
Name: Wordpress Context
Type: context
Expand All @@ -135,6 +191,8 @@ WordPress posts support the following formats:
- audio: An audio file or playlist. Could be used for Podcasting.
- chat: A chat transcript.

Before using the Create Post Tool, you MUST confirm the post title and content with the user.

## End of instructions for using Wordpress tools

---
Expand Down
57 changes: 57 additions & 0 deletions wordpress/tools/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import os
from requests.auth import HTTPBasicAuth
from datetime import datetime
import gptscript
import asyncio


if "WORDPRESS_USERNAME" not in os.environ:
raise ValueError("WORDPRESS_USERNAME is not set")
Expand Down Expand Up @@ -48,6 +51,60 @@ def is_valid_iso8601(date_string):
return False


def _prepend_base_path(base_path: str, file_path: str):
"""
Prepend a base path to a file path if it's not already rooted in the base path.
Args:
base_path (str): The base path to prepend.
file_path (str): The file path to check and modify.
Returns:
str: The modified file path with the base path prepended if necessary.
Examples:
>>> prepend_base_path("files", "my-file.txt")
'files/my-file.txt'
>>> prepend_base_path("files", "files/my-file.txt")
'files/my-file.txt'
>>> prepend_base_path("files", "foo/my-file.txt")
'files/foo/my-file.txt'
>>> prepend_base_path("files", "bar/files/my-file.txt")
'files/bar/files/my-file.txt'
>>> prepend_base_path("files", "files/bar/files/my-file.txt")
'files/bar/files/my-file.txt'
"""
# Split the file path into parts for checking
file_parts = os.path.normpath(file_path).split(os.sep)

# Check if the base path is already at the root
if file_parts[0] == base_path:
return file_path

# Prepend the base path
return os.path.join(base_path, file_path)


# for gptscript workspace S/L, see https://github.com/gptscript-ai/py-gptscript/blob/main/gptscript/gptscript.py


def load_from_gptscript_workspace(filepath: str) -> bytes:
gptscript_client = gptscript.GPTScript()
wksp_file_path = _prepend_base_path("files", filepath)

try:
return asyncio.run(gptscript_client.read_file_in_workspace(wksp_file_path))
except RuntimeError: # If there's already an event loop running
loop = asyncio.get_running_loop()
return loop.run_until_complete(
gptscript_client.read_file_in_workspace(wksp_file_path)
)


def str_to_bool(value):
"""Convert a string to a boolean."""
return str(value).lower() in ("true", "1", "yes")
Expand Down
Loading

0 comments on commit 7db1ab6

Please sign in to comment.