diff --git a/apps/sim/blocks/blocks/wordpress.ts b/apps/sim/blocks/blocks/wordpress.ts index b451b6a1a41..cb38487859e 100644 --- a/apps/sim/blocks/blocks/wordpress.ts +++ b/apps/sim/blocks/blocks/wordpress.ts @@ -11,7 +11,7 @@ export const WordPressBlock: BlockConfig = { description: 'Manage WordPress content', authMode: AuthMode.OAuth, longDescription: - 'Integrate with WordPress to create, update, and manage posts, pages, media, comments, categories, tags, and users. Supports WordPress.com sites via OAuth and self-hosted WordPress sites using Application Passwords authentication.', + 'Integrate with WordPress.com to create, update, and manage posts, pages, media, comments, categories, tags, and users. Connects to WordPress.com sites via OAuth.', docsLink: 'https://docs.sim.ai/integrations/wordpress', category: 'tools', integrationType: IntegrationType.Marketing, @@ -49,9 +49,15 @@ export const WordPressBlock: BlockConfig = { { label: 'Delete Comment', id: 'wordpress_delete_comment' }, // Categories { label: 'Create Category', id: 'wordpress_create_category' }, + { label: 'Update Category', id: 'wordpress_update_category' }, + { label: 'Delete Category', id: 'wordpress_delete_category' }, + { label: 'Get Category', id: 'wordpress_get_category' }, { label: 'List Categories', id: 'wordpress_list_categories' }, // Tags { label: 'Create Tag', id: 'wordpress_create_tag' }, + { label: 'Update Tag', id: 'wordpress_update_tag' }, + { label: 'Delete Tag', id: 'wordpress_delete_tag' }, + { label: 'Get Tag', id: 'wordpress_get_tag' }, { label: 'List Tags', id: 'wordpress_list_tags' }, // Users { label: 'Get Current User', id: 'wordpress_get_current_user' }, @@ -208,7 +214,7 @@ export const WordPressBlock: BlockConfig = { }, }, - // Categories (for posts only) + // Categories (for posts) { id: 'categories', title: 'Categories', @@ -217,11 +223,11 @@ export const WordPressBlock: BlockConfig = { mode: 'advanced', condition: { field: 'operation', - value: ['wordpress_create_post', 'wordpress_update_post'], + value: ['wordpress_create_post', 'wordpress_update_post', 'wordpress_list_posts'], }, }, - // Tags (for posts only) + // Tags (for posts) { id: 'tags', title: 'Tags', @@ -230,10 +236,20 @@ export const WordPressBlock: BlockConfig = { mode: 'advanced', condition: { field: 'operation', - value: ['wordpress_create_post', 'wordpress_update_post'], + value: ['wordpress_create_post', 'wordpress_update_post', 'wordpress_list_posts'], }, }, + // List Posts: Author filter + { + id: 'listAuthor', + title: 'Author ID', + type: 'short-input', + placeholder: 'Filter by author ID', + mode: 'advanced', + condition: { field: 'operation', value: 'wordpress_list_posts' }, + }, + // Featured Media ID { id: 'featuredMedia', @@ -277,7 +293,7 @@ export const WordPressBlock: BlockConfig = { mode: 'advanced', condition: { field: 'operation', - value: ['wordpress_create_page', 'wordpress_update_page'], + value: ['wordpress_create_page', 'wordpress_update_page', 'wordpress_list_pages'], }, }, @@ -349,6 +365,14 @@ export const WordPressBlock: BlockConfig = { mode: 'advanced', condition: { field: 'operation', value: 'wordpress_upload_media' }, }, + { + id: 'mediaDescription', + title: 'Description', + type: 'long-input', + placeholder: 'Media description', + mode: 'advanced', + condition: { field: 'operation', value: 'wordpress_upload_media' }, + }, { id: 'mediaId', title: 'Media ID', @@ -385,7 +409,10 @@ export const WordPressBlock: BlockConfig = { title: 'Post ID', type: 'short-input', placeholder: 'Post ID to comment on', - condition: { field: 'operation', value: 'wordpress_create_comment' }, + condition: { + field: 'operation', + value: ['wordpress_create_comment', 'wordpress_list_comments'], + }, required: { field: 'operation', value: 'wordpress_create_comment' }, }, { @@ -399,6 +426,38 @@ export const WordPressBlock: BlockConfig = { }, required: { field: 'operation', value: 'wordpress_create_comment' }, }, + { + id: 'commentParent', + title: 'Parent Comment ID', + type: 'short-input', + placeholder: 'Parent comment ID (for replies)', + mode: 'advanced', + condition: { field: 'operation', value: 'wordpress_create_comment' }, + }, + { + id: 'commentAuthorName', + title: 'Author Name', + type: 'short-input', + placeholder: 'Comment author display name', + mode: 'advanced', + condition: { field: 'operation', value: 'wordpress_create_comment' }, + }, + { + id: 'commentAuthorEmail', + title: 'Author Email', + type: 'short-input', + placeholder: 'Comment author email', + mode: 'advanced', + condition: { field: 'operation', value: 'wordpress_create_comment' }, + }, + { + id: 'commentAuthorUrl', + title: 'Author URL', + type: 'short-input', + placeholder: 'Comment author URL', + mode: 'advanced', + condition: { field: 'operation', value: 'wordpress_create_comment' }, + }, { id: 'commentId', title: 'Comment ID', @@ -429,12 +488,29 @@ export const WordPressBlock: BlockConfig = { }, // Category Operations + { + id: 'categoryId', + title: 'Category ID', + type: 'short-input', + placeholder: 'Enter category ID', + condition: { + field: 'operation', + value: ['wordpress_get_category', 'wordpress_update_category', 'wordpress_delete_category'], + }, + required: { + field: 'operation', + value: ['wordpress_get_category', 'wordpress_update_category', 'wordpress_delete_category'], + }, + }, { id: 'categoryName', title: 'Category Name', type: 'short-input', placeholder: 'Category name', - condition: { field: 'operation', value: 'wordpress_create_category' }, + condition: { + field: 'operation', + value: ['wordpress_create_category', 'wordpress_update_category'], + }, required: { field: 'operation', value: 'wordpress_create_category' }, }, { @@ -443,7 +519,10 @@ export const WordPressBlock: BlockConfig = { type: 'long-input', placeholder: 'Category description', mode: 'advanced', - condition: { field: 'operation', value: 'wordpress_create_category' }, + condition: { + field: 'operation', + value: ['wordpress_create_category', 'wordpress_update_category'], + }, }, { id: 'categoryParent', @@ -451,7 +530,10 @@ export const WordPressBlock: BlockConfig = { type: 'short-input', placeholder: 'Parent category ID', mode: 'advanced', - condition: { field: 'operation', value: 'wordpress_create_category' }, + condition: { + field: 'operation', + value: ['wordpress_create_category', 'wordpress_update_category'], + }, }, { id: 'categorySlug', @@ -459,16 +541,36 @@ export const WordPressBlock: BlockConfig = { type: 'short-input', placeholder: 'URL slug (optional)', mode: 'advanced', - condition: { field: 'operation', value: 'wordpress_create_category' }, + condition: { + field: 'operation', + value: ['wordpress_create_category', 'wordpress_update_category'], + }, }, // Tag Operations + { + id: 'tagId', + title: 'Tag ID', + type: 'short-input', + placeholder: 'Enter tag ID', + condition: { + field: 'operation', + value: ['wordpress_get_tag', 'wordpress_update_tag', 'wordpress_delete_tag'], + }, + required: { + field: 'operation', + value: ['wordpress_get_tag', 'wordpress_update_tag', 'wordpress_delete_tag'], + }, + }, { id: 'tagName', title: 'Tag Name', type: 'short-input', placeholder: 'Tag name', - condition: { field: 'operation', value: 'wordpress_create_tag' }, + condition: { + field: 'operation', + value: ['wordpress_create_tag', 'wordpress_update_tag'], + }, required: { field: 'operation', value: 'wordpress_create_tag' }, }, { @@ -477,7 +579,10 @@ export const WordPressBlock: BlockConfig = { type: 'long-input', placeholder: 'Tag description', mode: 'advanced', - condition: { field: 'operation', value: 'wordpress_create_tag' }, + condition: { + field: 'operation', + value: ['wordpress_create_tag', 'wordpress_update_tag'], + }, }, { id: 'tagSlug', @@ -485,7 +590,10 @@ export const WordPressBlock: BlockConfig = { type: 'short-input', placeholder: 'URL slug (optional)', mode: 'advanced', - condition: { field: 'operation', value: 'wordpress_create_tag' }, + condition: { + field: 'operation', + value: ['wordpress_create_tag', 'wordpress_update_tag'], + }, }, // User Operations @@ -523,7 +631,6 @@ export const WordPressBlock: BlockConfig = { { label: 'All Types', id: '' }, { label: 'Post', id: 'post' }, { label: 'Page', id: 'page' }, - { label: 'Attachment', id: 'attachment' }, ], value: () => '', mode: 'advanced', @@ -665,12 +772,7 @@ export const WordPressBlock: BlockConfig = { mode: 'advanced', condition: { field: 'operation', - value: [ - 'wordpress_delete_post', - 'wordpress_delete_page', - 'wordpress_delete_media', - 'wordpress_delete_comment', - ], + value: ['wordpress_delete_post', 'wordpress_delete_page', 'wordpress_delete_comment'], }, }, ], @@ -696,8 +798,14 @@ export const WordPressBlock: BlockConfig = { 'wordpress_delete_comment', 'wordpress_create_category', 'wordpress_list_categories', + 'wordpress_get_category', + 'wordpress_update_category', + 'wordpress_delete_category', 'wordpress_create_tag', 'wordpress_list_tags', + 'wordpress_get_tag', + 'wordpress_update_tag', + 'wordpress_delete_tag', 'wordpress_get_current_user', 'wordpress_list_users', 'wordpress_get_user', @@ -723,7 +831,10 @@ export const WordPressBlock: BlockConfig = { slug: params.slug, categories: params.categories, tags: params.tags, - featuredMedia: params.featuredMedia ? Number(params.featuredMedia) : undefined, + featuredMedia: + params.featuredMedia !== undefined && params.featuredMedia !== '' + ? Number(params.featuredMedia) + : undefined, } case 'wordpress_update_post': return { @@ -736,7 +847,10 @@ export const WordPressBlock: BlockConfig = { slug: params.slug, categories: params.categories, tags: params.tags, - featuredMedia: params.featuredMedia ? Number(params.featuredMedia) : undefined, + featuredMedia: + params.featuredMedia !== undefined && params.featuredMedia !== '' + ? Number(params.featuredMedia) + : undefined, } case 'wordpress_delete_post': return { @@ -760,6 +874,10 @@ export const WordPressBlock: BlockConfig = { order: params.order, categories: params.categories, tags: params.tags, + author: + params.listAuthor !== undefined && params.listAuthor !== '' + ? Number(params.listAuthor) + : undefined, } case 'wordpress_create_page': return { @@ -769,9 +887,18 @@ export const WordPressBlock: BlockConfig = { status: params.status, excerpt: params.excerpt, slug: params.slug, - parent: params.parent ? Number(params.parent) : undefined, - menuOrder: params.menuOrder ? Number(params.menuOrder) : undefined, - featuredMedia: params.featuredMedia ? Number(params.featuredMedia) : undefined, + parent: + params.parent !== undefined && params.parent !== '' + ? Number(params.parent) + : undefined, + menuOrder: + params.menuOrder !== undefined && params.menuOrder !== '' + ? Number(params.menuOrder) + : undefined, + featuredMedia: + params.featuredMedia !== undefined && params.featuredMedia !== '' + ? Number(params.featuredMedia) + : undefined, } case 'wordpress_update_page': return { @@ -782,9 +909,18 @@ export const WordPressBlock: BlockConfig = { status: params.status, excerpt: params.excerpt, slug: params.slug, - parent: params.parent ? Number(params.parent) : undefined, - menuOrder: params.menuOrder ? Number(params.menuOrder) : undefined, - featuredMedia: params.featuredMedia ? Number(params.featuredMedia) : undefined, + parent: + params.parent !== undefined && params.parent !== '' + ? Number(params.parent) + : undefined, + menuOrder: + params.menuOrder !== undefined && params.menuOrder !== '' + ? Number(params.menuOrder) + : undefined, + featuredMedia: + params.featuredMedia !== undefined && params.featuredMedia !== '' + ? Number(params.featuredMedia) + : undefined, } case 'wordpress_delete_page': return { @@ -806,7 +942,10 @@ export const WordPressBlock: BlockConfig = { search: params.search, orderBy: params.orderBy, order: params.order, - parent: params.parent ? Number(params.parent) : undefined, + parent: + params.parent !== undefined && params.parent !== '' + ? Number(params.parent) + : undefined, } case 'wordpress_upload_media': // file is the canonical param for both basic (fileUpload) and advanced modes @@ -817,6 +956,7 @@ export const WordPressBlock: BlockConfig = { title: params.mediaTitle, caption: params.caption, altText: params.altText, + description: params.mediaDescription || undefined, } case 'wordpress_get_media': return { @@ -837,13 +977,19 @@ export const WordPressBlock: BlockConfig = { return { ...baseParams, mediaId: Number(params.mediaId), - force: params.force, } case 'wordpress_create_comment': return { ...baseParams, postId: Number(params.commentPostId), content: params.commentContent, + parent: + params.commentParent !== undefined && params.commentParent !== '' + ? Number(params.commentParent) + : undefined, + authorName: params.commentAuthorName || undefined, + authorEmail: params.commentAuthorEmail || undefined, + authorUrl: params.commentAuthorUrl || undefined, } case 'wordpress_list_comments': return { @@ -873,7 +1019,10 @@ export const WordPressBlock: BlockConfig = { ...baseParams, name: params.categoryName, description: params.categoryDescription, - parent: params.categoryParent ? Number(params.categoryParent) : undefined, + parent: + params.categoryParent !== undefined && params.categoryParent !== '' + ? Number(params.categoryParent) + : undefined, slug: params.categorySlug, } case 'wordpress_list_categories': @@ -884,6 +1033,28 @@ export const WordPressBlock: BlockConfig = { search: params.search, order: params.order, } + case 'wordpress_get_category': + return { + ...baseParams, + categoryId: Number(params.categoryId), + } + case 'wordpress_update_category': + return { + ...baseParams, + categoryId: Number(params.categoryId), + name: params.categoryName, + description: params.categoryDescription, + parent: + params.categoryParent !== undefined && params.categoryParent !== '' + ? Number(params.categoryParent) + : undefined, + slug: params.categorySlug, + } + case 'wordpress_delete_category': + return { + ...baseParams, + categoryId: Number(params.categoryId), + } case 'wordpress_create_tag': return { ...baseParams, @@ -899,6 +1070,24 @@ export const WordPressBlock: BlockConfig = { search: params.search, order: params.order, } + case 'wordpress_get_tag': + return { + ...baseParams, + tagId: Number(params.tagId), + } + case 'wordpress_update_tag': + return { + ...baseParams, + tagId: Number(params.tagId), + name: params.tagName, + description: params.tagDescription, + slug: params.tagSlug, + } + case 'wordpress_delete_tag': + return { + ...baseParams, + tagId: Number(params.tagId), + } case 'wordpress_get_current_user': return baseParams case 'wordpress_list_users': @@ -921,7 +1110,7 @@ export const WordPressBlock: BlockConfig = { query: params.query, perPage: params.perPage ? Number(params.perPage) : undefined, page: params.page ? Number(params.page) : undefined, - type: params.searchType || undefined, + subtype: params.searchType || undefined, } default: return baseParams @@ -942,6 +1131,7 @@ export const WordPressBlock: BlockConfig = { slug: { type: 'string', description: 'URL slug' }, categories: { type: 'string', description: 'Category IDs (comma-separated)' }, tags: { type: 'string', description: 'Tag IDs (comma-separated)' }, + listAuthor: { type: 'number', description: 'Filter posts by author ID' }, featuredMedia: { type: 'number', description: 'Featured media ID' }, // Page inputs pageId: { type: 'number', description: 'Page ID' }, @@ -953,19 +1143,26 @@ export const WordPressBlock: BlockConfig = { mediaTitle: { type: 'string', description: 'Media title' }, caption: { type: 'string', description: 'Media caption' }, altText: { type: 'string', description: 'Alt text' }, + mediaDescription: { type: 'string', description: 'Media description' }, mediaId: { type: 'number', description: 'Media ID' }, mediaType: { type: 'string', description: 'Media type filter' }, // Comment inputs commentPostId: { type: 'number', description: 'Post ID for comment' }, commentContent: { type: 'string', description: 'Comment content' }, + commentParent: { type: 'number', description: 'Parent comment ID for replies' }, + commentAuthorName: { type: 'string', description: 'Comment author display name' }, + commentAuthorEmail: { type: 'string', description: 'Comment author email' }, + commentAuthorUrl: { type: 'string', description: 'Comment author URL' }, commentId: { type: 'number', description: 'Comment ID' }, commentStatus: { type: 'string', description: 'Comment status' }, // Category inputs + categoryId: { type: 'number', description: 'Category ID' }, categoryName: { type: 'string', description: 'Category name' }, categoryDescription: { type: 'string', description: 'Category description' }, categoryParent: { type: 'number', description: 'Parent category ID' }, categorySlug: { type: 'string', description: 'Category slug' }, // Tag inputs + tagId: { type: 'number', description: 'Tag ID' }, tagName: { type: 'string', description: 'Tag name' }, tagDescription: { type: 'string', description: 'Tag description' }, tagSlug: { type: 'string', description: 'Tag slug' }, @@ -974,7 +1171,10 @@ export const WordPressBlock: BlockConfig = { roles: { type: 'string', description: 'User roles filter' }, // Search inputs query: { type: 'string', description: 'Search query' }, - searchType: { type: 'string', description: 'Content type filter' }, + searchType: { + type: 'string', + description: 'Content subtype filter (post, page) — maps to the API subtype param', + }, // List inputs perPage: { type: 'number', description: 'Results per page' }, page: { type: 'number', description: 'Page number' }, @@ -983,7 +1183,6 @@ export const WordPressBlock: BlockConfig = { order: { type: 'string', description: 'Order direction' }, listStatus: { type: 'string', description: 'Status filter' }, force: { type: 'boolean', description: 'Force delete' }, - hideEmpty: { type: 'boolean', description: 'Hide empty taxonomies' }, }, outputs: { // Post outputs @@ -1114,5 +1313,19 @@ export const WordPressBlockMeta = { content: '# Moderate WordPress Comments\n\nKeep the comment queue clean and on-policy.\n\n## Steps\n1. List comments, optionally filtering by status such as hold.\n2. For each comment, judge it against the moderation policy: legitimate, spam, or abusive.\n3. Update each comment to the right status: approved, hold, spam, or trash.\n\n## Output\nReturn a summary of how many comments were approved, held, marked spam, or trashed, with the comment IDs grouped by action taken.', }, + { + name: 'organize-taxonomy', + description: + 'Clean up WordPress categories and tags: rename, re-slug, re-parent, or remove unused ones.', + content: + '# Organize WordPress Taxonomy\n\nKeep categories and tags tidy and consistent.\n\n## Steps\n1. List existing categories and tags to see the current taxonomy, including each item post count.\n2. Decide the target structure: rename to a consistent style, fix slugs, set parents for hierarchy, or remove duplicates and empties.\n3. For renames or re-parenting, update the category or tag by ID with the new name, slug, or parent.\n4. To remove one, get it first to confirm it is the right term and low-usage, then delete it (deletion is permanent for terms).\n\n## Output\nReport what changed for each term: renamed, re-slugged, re-parented, or deleted, with the term IDs. Note any term skipped because it still had many posts.', + }, + { + name: 'audit-site-content', + description: + 'Inventory WordPress content by searching and listing posts and pages to find gaps or issues.', + content: + '# Audit WordPress Content\n\nBuild an inventory of what is on the site.\n\n## Steps\n1. Use search across content, or list posts and pages with filters such as status and date order.\n2. Page through results using the total and totalPages counts so nothing is missed.\n3. Group findings by status, category, or age to spot drafts left unpublished, stale posts, or thin content.\n\n## Output\nReturn a structured inventory: counts by status and type, plus a list of flagged items (IDs, titles, and URLs) that need attention.', + }, ], } as const satisfies BlockMeta diff --git a/apps/sim/tools/registry.ts b/apps/sim/tools/registry.ts index 4adbd38fb46..4c9fe89ed76 100644 --- a/apps/sim/tools/registry.ts +++ b/apps/sim/tools/registry.ts @@ -4123,14 +4123,18 @@ import { wordpressCreatePageTool, wordpressCreatePostTool, wordpressCreateTagTool, + wordpressDeleteCategoryTool, wordpressDeleteCommentTool, wordpressDeleteMediaTool, wordpressDeletePageTool, wordpressDeletePostTool, + wordpressDeleteTagTool, + wordpressGetCategoryTool, wordpressGetCurrentUserTool, wordpressGetMediaTool, wordpressGetPageTool, wordpressGetPostTool, + wordpressGetTagTool, wordpressGetUserTool, wordpressListCategoriesTool, wordpressListCommentsTool, @@ -4140,9 +4144,11 @@ import { wordpressListTagsTool, wordpressListUsersTool, wordpressSearchContentTool, + wordpressUpdateCategoryTool, wordpressUpdateCommentTool, wordpressUpdatePageTool, wordpressUpdatePostTool, + wordpressUpdateTagTool, wordpressUploadMediaTool, } from '@/tools/wordpress' import { @@ -7421,8 +7427,14 @@ export const tools: Record = { wordpress_delete_comment: wordpressDeleteCommentTool, wordpress_create_category: wordpressCreateCategoryTool, wordpress_list_categories: wordpressListCategoriesTool, + wordpress_get_category: wordpressGetCategoryTool, + wordpress_update_category: wordpressUpdateCategoryTool, + wordpress_delete_category: wordpressDeleteCategoryTool, wordpress_create_tag: wordpressCreateTagTool, wordpress_list_tags: wordpressListTagsTool, + wordpress_get_tag: wordpressGetTagTool, + wordpress_update_tag: wordpressUpdateTagTool, + wordpress_delete_tag: wordpressDeleteTagTool, wordpress_get_current_user: wordpressGetCurrentUserTool, wordpress_list_users: wordpressListUsersTool, wordpress_get_user: wordpressGetUserTool, diff --git a/apps/sim/tools/wordpress/create_category.ts b/apps/sim/tools/wordpress/create_category.ts index 61bb4076a34..f787b60b186 100644 --- a/apps/sim/tools/wordpress/create_category.ts +++ b/apps/sim/tools/wordpress/create_category.ts @@ -66,7 +66,7 @@ export const createCategoryTool: ToolConfig< } if (params.description) body.description = params.description - if (params.parent) body.parent = params.parent + if (params.parent !== undefined) body.parent = params.parent if (params.slug) body.slug = params.slug return body diff --git a/apps/sim/tools/wordpress/create_comment.ts b/apps/sim/tools/wordpress/create_comment.ts index d4f473105f1..dd6fb5898b1 100644 --- a/apps/sim/tools/wordpress/create_comment.ts +++ b/apps/sim/tools/wordpress/create_comment.ts @@ -78,7 +78,7 @@ export const createCommentTool: ToolConfig< content: params.content, } - if (params.parent) body.parent = params.parent + if (params.parent !== undefined) body.parent = params.parent if (params.authorName) body.author_name = params.authorName if (params.authorEmail) body.author_email = params.authorEmail if (params.authorUrl) body.author_url = params.authorUrl diff --git a/apps/sim/tools/wordpress/create_page.ts b/apps/sim/tools/wordpress/create_page.ts index 161cd10fb8d..2a7f7658f74 100644 --- a/apps/sim/tools/wordpress/create_page.ts +++ b/apps/sim/tools/wordpress/create_page.ts @@ -90,9 +90,9 @@ export const createPageTool: ToolConfig = { + id: 'wordpress_delete_category', + name: 'WordPress Delete Category', + description: 'Delete a category from WordPress.com', + version: '1.0.0', + + oauth: { + required: true, + provider: 'wordpress', + requiredScopes: ['global'], + }, + + params: { + siteId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'WordPress.com site ID or domain (e.g., 12345678 or mysite.wordpress.com)', + }, + categoryId: { + type: 'number', + required: true, + visibility: 'user-or-llm', + description: 'The ID of the category to delete', + }, + }, + + request: { + url: (params) => { + // Terms do not support trashing, so force=true is required to delete. + return `${WORDPRESS_COM_API_BASE}/${params.siteId}/categories/${params.categoryId}?force=true` + }, + method: 'DELETE', + headers: (params) => ({ + 'Content-Type': 'application/json', + Authorization: `Bearer ${params.accessToken}`, + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const error = await response.json().catch(() => ({})) + throw new Error(error.message || `WordPress API error: ${response.status}`) + } + + const data = await response.json() + + return { + success: true, + output: { + deleted: data.deleted ?? true, + category: { + id: data.id ?? data.previous?.id, + count: data.count ?? data.previous?.count, + description: data.description || data.previous?.description, + link: data.link || data.previous?.link, + name: data.name || data.previous?.name, + slug: data.slug || data.previous?.slug, + taxonomy: data.taxonomy || data.previous?.taxonomy, + parent: data.parent ?? data.previous?.parent, + }, + }, + } + }, + + outputs: { + deleted: { + type: 'boolean', + description: 'Whether the category was deleted', + }, + category: { + type: 'object', + description: 'The deleted category', + properties: { + id: { type: 'number', description: 'Category ID' }, + count: { type: 'number', description: 'Number of posts in this category' }, + description: { type: 'string', description: 'Category description' }, + link: { type: 'string', description: 'Category archive URL' }, + name: { type: 'string', description: 'Category name' }, + slug: { type: 'string', description: 'Category slug' }, + taxonomy: { type: 'string', description: 'Taxonomy name' }, + parent: { type: 'number', description: 'Parent category ID' }, + }, + }, + }, +} diff --git a/apps/sim/tools/wordpress/delete_comment.ts b/apps/sim/tools/wordpress/delete_comment.ts index 5aec306e5d8..03d4b6081df 100644 --- a/apps/sim/tools/wordpress/delete_comment.ts +++ b/apps/sim/tools/wordpress/delete_comment.ts @@ -64,12 +64,12 @@ export const deleteCommentTool: ToolConfig< return { success: true, output: { - deleted: data.deleted || true, + deleted: data.deleted ?? true, comment: { - id: data.id || data.previous?.id, - post: data.post || data.previous?.post, - parent: data.parent || data.previous?.parent, - author: data.author || data.previous?.author, + id: data.id ?? data.previous?.id, + post: data.post ?? data.previous?.post, + parent: data.parent ?? data.previous?.parent, + author: data.author ?? data.previous?.author, author_name: data.author_name || data.previous?.author_name, author_email: data.author_email || data.previous?.author_email, author_url: data.author_url || data.previous?.author_url, diff --git a/apps/sim/tools/wordpress/delete_media.ts b/apps/sim/tools/wordpress/delete_media.ts index 3b680919e3d..0dfc8e0b1de 100644 --- a/apps/sim/tools/wordpress/delete_media.ts +++ b/apps/sim/tools/wordpress/delete_media.ts @@ -31,17 +31,11 @@ export const deleteMediaTool: ToolConfig { - // Media deletion requires force=true to actually delete + // Media has no trash — deletion always requires force=true to take effect return `${WORDPRESS_COM_API_BASE}/${params.siteId}/media/${params.mediaId}?force=true` }, method: 'DELETE', @@ -62,9 +56,9 @@ export const deleteMediaTool: ToolConfig = { + id: 'wordpress_delete_tag', + name: 'WordPress Delete Tag', + description: 'Delete a tag from WordPress.com', + version: '1.0.0', + + oauth: { + required: true, + provider: 'wordpress', + requiredScopes: ['global'], + }, + + params: { + siteId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'WordPress.com site ID or domain (e.g., 12345678 or mysite.wordpress.com)', + }, + tagId: { + type: 'number', + required: true, + visibility: 'user-or-llm', + description: 'The ID of the tag to delete', + }, + }, + + request: { + url: (params) => { + // Terms do not support trashing, so force=true is required to delete. + return `${WORDPRESS_COM_API_BASE}/${params.siteId}/tags/${params.tagId}?force=true` + }, + method: 'DELETE', + headers: (params) => ({ + 'Content-Type': 'application/json', + Authorization: `Bearer ${params.accessToken}`, + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const error = await response.json().catch(() => ({})) + throw new Error(error.message || `WordPress API error: ${response.status}`) + } + + const data = await response.json() + + return { + success: true, + output: { + deleted: data.deleted ?? true, + tag: { + id: data.id ?? data.previous?.id, + count: data.count ?? data.previous?.count, + description: data.description || data.previous?.description, + link: data.link || data.previous?.link, + name: data.name || data.previous?.name, + slug: data.slug || data.previous?.slug, + taxonomy: data.taxonomy || data.previous?.taxonomy, + }, + }, + } + }, + + outputs: { + deleted: { + type: 'boolean', + description: 'Whether the tag was deleted', + }, + tag: { + type: 'object', + description: 'The deleted tag', + properties: { + id: { type: 'number', description: 'Tag ID' }, + count: { type: 'number', description: 'Number of posts with this tag' }, + description: { type: 'string', description: 'Tag description' }, + link: { type: 'string', description: 'Tag archive URL' }, + name: { type: 'string', description: 'Tag name' }, + slug: { type: 'string', description: 'Tag slug' }, + taxonomy: { type: 'string', description: 'Taxonomy name' }, + }, + }, + }, +} diff --git a/apps/sim/tools/wordpress/get_category.ts b/apps/sim/tools/wordpress/get_category.ts new file mode 100644 index 00000000000..968dafe7fbc --- /dev/null +++ b/apps/sim/tools/wordpress/get_category.ts @@ -0,0 +1,86 @@ +import type { ToolConfig } from '@/tools/types' +import { + WORDPRESS_COM_API_BASE, + type WordPressGetCategoryParams, + type WordPressGetCategoryResponse, +} from '@/tools/wordpress/types' + +export const getCategoryTool: ToolConfig = + { + id: 'wordpress_get_category', + name: 'WordPress Get Category', + description: 'Get a single category from WordPress.com by ID', + version: '1.0.0', + + oauth: { + required: true, + provider: 'wordpress', + requiredScopes: ['global'], + }, + + params: { + siteId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'WordPress.com site ID or domain (e.g., 12345678 or mysite.wordpress.com)', + }, + categoryId: { + type: 'number', + required: true, + visibility: 'user-or-llm', + description: 'The ID of the category to retrieve', + }, + }, + + request: { + url: (params) => `${WORDPRESS_COM_API_BASE}/${params.siteId}/categories/${params.categoryId}`, + method: 'GET', + headers: (params) => ({ + 'Content-Type': 'application/json', + Authorization: `Bearer ${params.accessToken}`, + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const error = await response.json().catch(() => ({})) + throw new Error(error.message || `WordPress API error: ${response.status}`) + } + + const data = await response.json() + + return { + success: true, + output: { + category: { + id: data.id, + count: data.count, + description: data.description, + link: data.link, + name: data.name, + slug: data.slug, + taxonomy: data.taxonomy, + parent: data.parent, + }, + }, + } + }, + + outputs: { + category: { + type: 'object', + description: 'The retrieved category', + properties: { + id: { type: 'number', description: 'Category ID' }, + count: { type: 'number', description: 'Number of posts in this category' }, + description: { type: 'string', description: 'Category description' }, + link: { type: 'string', description: 'Category archive URL' }, + name: { type: 'string', description: 'Category name' }, + slug: { type: 'string', description: 'Category slug' }, + taxonomy: { type: 'string', description: 'Taxonomy name' }, + parent: { type: 'number', description: 'Parent category ID' }, + }, + }, + }, + } diff --git a/apps/sim/tools/wordpress/get_tag.ts b/apps/sim/tools/wordpress/get_tag.ts new file mode 100644 index 00000000000..bc4645c4fcd --- /dev/null +++ b/apps/sim/tools/wordpress/get_tag.ts @@ -0,0 +1,83 @@ +import type { ToolConfig } from '@/tools/types' +import { + WORDPRESS_COM_API_BASE, + type WordPressGetTagParams, + type WordPressGetTagResponse, +} from '@/tools/wordpress/types' + +export const getTagTool: ToolConfig = { + id: 'wordpress_get_tag', + name: 'WordPress Get Tag', + description: 'Get a single tag from WordPress.com by ID', + version: '1.0.0', + + oauth: { + required: true, + provider: 'wordpress', + requiredScopes: ['global'], + }, + + params: { + siteId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'WordPress.com site ID or domain (e.g., 12345678 or mysite.wordpress.com)', + }, + tagId: { + type: 'number', + required: true, + visibility: 'user-or-llm', + description: 'The ID of the tag to retrieve', + }, + }, + + request: { + url: (params) => `${WORDPRESS_COM_API_BASE}/${params.siteId}/tags/${params.tagId}`, + method: 'GET', + headers: (params) => ({ + 'Content-Type': 'application/json', + Authorization: `Bearer ${params.accessToken}`, + }), + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const error = await response.json().catch(() => ({})) + throw new Error(error.message || `WordPress API error: ${response.status}`) + } + + const data = await response.json() + + return { + success: true, + output: { + tag: { + id: data.id, + count: data.count, + description: data.description, + link: data.link, + name: data.name, + slug: data.slug, + taxonomy: data.taxonomy, + }, + }, + } + }, + + outputs: { + tag: { + type: 'object', + description: 'The retrieved tag', + properties: { + id: { type: 'number', description: 'Tag ID' }, + count: { type: 'number', description: 'Number of posts with this tag' }, + description: { type: 'string', description: 'Tag description' }, + link: { type: 'string', description: 'Tag archive URL' }, + name: { type: 'string', description: 'Tag name' }, + slug: { type: 'string', description: 'Tag slug' }, + taxonomy: { type: 'string', description: 'Taxonomy name' }, + }, + }, + }, +} diff --git a/apps/sim/tools/wordpress/index.ts b/apps/sim/tools/wordpress/index.ts index 3889208a544..ab48592b46d 100644 --- a/apps/sim/tools/wordpress/index.ts +++ b/apps/sim/tools/wordpress/index.ts @@ -4,14 +4,18 @@ import { createCommentTool } from '@/tools/wordpress/create_comment' import { createPageTool } from '@/tools/wordpress/create_page' import { createPostTool } from '@/tools/wordpress/create_post' import { createTagTool } from '@/tools/wordpress/create_tag' +import { deleteCategoryTool } from '@/tools/wordpress/delete_category' import { deleteCommentTool } from '@/tools/wordpress/delete_comment' import { deleteMediaTool } from '@/tools/wordpress/delete_media' import { deletePageTool } from '@/tools/wordpress/delete_page' import { deletePostTool } from '@/tools/wordpress/delete_post' +import { deleteTagTool } from '@/tools/wordpress/delete_tag' +import { getCategoryTool } from '@/tools/wordpress/get_category' import { getCurrentUserTool } from '@/tools/wordpress/get_current_user' import { getMediaTool } from '@/tools/wordpress/get_media' import { getPageTool } from '@/tools/wordpress/get_page' import { getPostTool } from '@/tools/wordpress/get_post' +import { getTagTool } from '@/tools/wordpress/get_tag' import { getUserTool } from '@/tools/wordpress/get_user' import { listCategoriesTool } from '@/tools/wordpress/list_categories' import { listCommentsTool } from '@/tools/wordpress/list_comments' @@ -21,9 +25,11 @@ import { listPostsTool } from '@/tools/wordpress/list_posts' import { listTagsTool } from '@/tools/wordpress/list_tags' import { listUsersTool } from '@/tools/wordpress/list_users' import { searchContentTool } from '@/tools/wordpress/search_content' +import { updateCategoryTool } from '@/tools/wordpress/update_category' import { updateCommentTool } from '@/tools/wordpress/update_comment' import { updatePageTool } from '@/tools/wordpress/update_page' import { updatePostTool } from '@/tools/wordpress/update_post' +import { updateTagTool } from '@/tools/wordpress/update_tag' import { uploadMediaTool } from '@/tools/wordpress/upload_media' // Post operations @@ -55,10 +61,16 @@ export const wordpressDeleteCommentTool = deleteCommentTool // Category operations export const wordpressCreateCategoryTool = createCategoryTool export const wordpressListCategoriesTool = listCategoriesTool +export const wordpressGetCategoryTool = getCategoryTool +export const wordpressUpdateCategoryTool = updateCategoryTool +export const wordpressDeleteCategoryTool = deleteCategoryTool // Tag operations export const wordpressCreateTagTool = createTagTool export const wordpressListTagsTool = listTagsTool +export const wordpressGetTagTool = getTagTool +export const wordpressUpdateTagTool = updateTagTool +export const wordpressDeleteTagTool = deleteTagTool // User operations export const wordpressGetCurrentUserTool = getCurrentUserTool diff --git a/apps/sim/tools/wordpress/search_content.ts b/apps/sim/tools/wordpress/search_content.ts index 2d20340810c..706b510991b 100644 --- a/apps/sim/tools/wordpress/search_content.ts +++ b/apps/sim/tools/wordpress/search_content.ts @@ -36,26 +36,27 @@ export const searchContentTool: ToolConfig< perPage: { type: 'number', required: false, - visibility: 'user-only', + visibility: 'user-or-llm', description: 'Number of results per request (default: 10, max: 100)', }, page: { type: 'number', required: false, - visibility: 'user-only', + visibility: 'user-or-llm', description: 'Page number for pagination', }, type: { type: 'string', required: false, visibility: 'user-only', - description: 'Filter by content type: post, page, attachment', + description: 'Filter by search index type: post, term, or post-format', }, subtype: { type: 'string', required: false, visibility: 'user-only', - description: 'Filter by post type slug (e.g., post, page)', + description: + 'Filter by subtype within the selected type (e.g., post or page when type is post)', }, }, @@ -114,8 +115,11 @@ export const searchContentTool: ToolConfig< id: { type: 'number', description: 'Content ID' }, title: { type: 'string', description: 'Content title' }, url: { type: 'string', description: 'Content URL' }, - type: { type: 'string', description: 'Content type (post, page, attachment)' }, - subtype: { type: 'string', description: 'Post type slug' }, + type: { type: 'string', description: 'Content type (post, term, or post-format)' }, + subtype: { + type: 'string', + description: 'Subtype within the content type (e.g., post, page)', + }, }, }, }, diff --git a/apps/sim/tools/wordpress/types.ts b/apps/sim/tools/wordpress/types.ts index 81bc115e414..146b72905c1 100644 --- a/apps/sim/tools/wordpress/types.ts +++ b/apps/sim/tools/wordpress/types.ts @@ -325,7 +325,6 @@ export interface WordPressListMediaResponse extends ToolResponse { // Delete Media export interface WordPressDeleteMediaParams extends WordPressBaseParams { mediaId: number - force?: boolean } export interface WordPressDeleteMediaResponse extends ToolResponse { @@ -472,6 +471,44 @@ export interface WordPressListCategoriesResponse extends ToolResponse { } } +// Get Category +export interface WordPressGetCategoryParams extends WordPressBaseParams { + categoryId: number +} + +export interface WordPressGetCategoryResponse extends ToolResponse { + output: { + category: WordPressCategory + } +} + +// Update Category +export interface WordPressUpdateCategoryParams extends WordPressBaseParams { + categoryId: number + name?: string + description?: string + parent?: number + slug?: string +} + +export interface WordPressUpdateCategoryResponse extends ToolResponse { + output: { + category: WordPressCategory + } +} + +// Delete Category +export interface WordPressDeleteCategoryParams extends WordPressBaseParams { + categoryId: number +} + +export interface WordPressDeleteCategoryResponse extends ToolResponse { + output: { + deleted: boolean + category: WordPressCategory + } +} + // Create Tag export interface WordPressCreateTagParams extends WordPressBaseParams { name: string @@ -511,6 +548,43 @@ export interface WordPressListTagsResponse extends ToolResponse { } } +// Get Tag +export interface WordPressGetTagParams extends WordPressBaseParams { + tagId: number +} + +export interface WordPressGetTagResponse extends ToolResponse { + output: { + tag: WordPressTag + } +} + +// Update Tag +export interface WordPressUpdateTagParams extends WordPressBaseParams { + tagId: number + name?: string + description?: string + slug?: string +} + +export interface WordPressUpdateTagResponse extends ToolResponse { + output: { + tag: WordPressTag + } +} + +// Delete Tag +export interface WordPressDeleteTagParams extends WordPressBaseParams { + tagId: number +} + +export interface WordPressDeleteTagResponse extends ToolResponse { + output: { + deleted: boolean + tag: WordPressTag + } +} + // ============================================ // USER OPERATIONS // ============================================ @@ -576,7 +650,7 @@ export interface WordPressSearchContentParams extends WordPressBaseParams { query: string perPage?: number page?: number - type?: 'post' | 'page' | 'attachment' + type?: 'post' | 'term' | 'post-format' subtype?: string } @@ -620,8 +694,14 @@ export type WordPressResponse = | WordPressDeleteCommentResponse | WordPressCreateCategoryResponse | WordPressListCategoriesResponse + | WordPressGetCategoryResponse + | WordPressUpdateCategoryResponse + | WordPressDeleteCategoryResponse | WordPressCreateTagResponse | WordPressListTagsResponse + | WordPressGetTagResponse + | WordPressUpdateTagResponse + | WordPressDeleteTagResponse | WordPressGetCurrentUserResponse | WordPressListUsersResponse | WordPressGetUserResponse diff --git a/apps/sim/tools/wordpress/update_category.ts b/apps/sim/tools/wordpress/update_category.ts new file mode 100644 index 00000000000..cbb47510c21 --- /dev/null +++ b/apps/sim/tools/wordpress/update_category.ts @@ -0,0 +1,122 @@ +import type { ToolConfig } from '@/tools/types' +import { + WORDPRESS_COM_API_BASE, + type WordPressUpdateCategoryParams, + type WordPressUpdateCategoryResponse, +} from '@/tools/wordpress/types' + +export const updateCategoryTool: ToolConfig< + WordPressUpdateCategoryParams, + WordPressUpdateCategoryResponse +> = { + id: 'wordpress_update_category', + name: 'WordPress Update Category', + description: 'Update an existing category in WordPress.com', + version: '1.0.0', + + oauth: { + required: true, + provider: 'wordpress', + requiredScopes: ['global'], + }, + + params: { + siteId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'WordPress.com site ID or domain (e.g., 12345678 or mysite.wordpress.com)', + }, + categoryId: { + type: 'number', + required: true, + visibility: 'user-or-llm', + description: 'The ID of the category to update', + }, + name: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Category name', + }, + description: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Category description', + }, + parent: { + type: 'number', + required: false, + visibility: 'user-only', + description: 'Parent category ID for hierarchical categories', + }, + slug: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'URL slug for the category', + }, + }, + + request: { + url: (params) => `${WORDPRESS_COM_API_BASE}/${params.siteId}/categories/${params.categoryId}`, + method: 'POST', + headers: (params) => ({ + 'Content-Type': 'application/json', + Authorization: `Bearer ${params.accessToken}`, + }), + body: (params) => { + const body: Record = {} + + if (params.name) body.name = params.name + if (params.description) body.description = params.description + if (params.parent !== undefined) body.parent = params.parent + if (params.slug) body.slug = params.slug + + return body + }, + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const error = await response.json().catch(() => ({})) + throw new Error(error.message || `WordPress API error: ${response.status}`) + } + + const data = await response.json() + + return { + success: true, + output: { + category: { + id: data.id, + count: data.count, + description: data.description, + link: data.link, + name: data.name, + slug: data.slug, + taxonomy: data.taxonomy, + parent: data.parent, + }, + }, + } + }, + + outputs: { + category: { + type: 'object', + description: 'The updated category', + properties: { + id: { type: 'number', description: 'Category ID' }, + count: { type: 'number', description: 'Number of posts in this category' }, + description: { type: 'string', description: 'Category description' }, + link: { type: 'string', description: 'Category archive URL' }, + name: { type: 'string', description: 'Category name' }, + slug: { type: 'string', description: 'Category slug' }, + taxonomy: { type: 'string', description: 'Taxonomy name' }, + parent: { type: 'number', description: 'Parent category ID' }, + }, + }, + }, +} diff --git a/apps/sim/tools/wordpress/update_page.ts b/apps/sim/tools/wordpress/update_page.ts index 37d3dc1d0fb..0c7fe51b79b 100644 --- a/apps/sim/tools/wordpress/update_page.ts +++ b/apps/sim/tools/wordpress/update_page.ts @@ -97,7 +97,7 @@ export const updatePageTool: ToolConfig = { + id: 'wordpress_update_tag', + name: 'WordPress Update Tag', + description: 'Update an existing tag in WordPress.com', + version: '1.0.0', + + oauth: { + required: true, + provider: 'wordpress', + requiredScopes: ['global'], + }, + + params: { + siteId: { + type: 'string', + required: true, + visibility: 'user-or-llm', + description: 'WordPress.com site ID or domain (e.g., 12345678 or mysite.wordpress.com)', + }, + tagId: { + type: 'number', + required: true, + visibility: 'user-or-llm', + description: 'The ID of the tag to update', + }, + name: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Tag name', + }, + description: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'Tag description', + }, + slug: { + type: 'string', + required: false, + visibility: 'user-or-llm', + description: 'URL slug for the tag', + }, + }, + + request: { + url: (params) => `${WORDPRESS_COM_API_BASE}/${params.siteId}/tags/${params.tagId}`, + method: 'POST', + headers: (params) => ({ + 'Content-Type': 'application/json', + Authorization: `Bearer ${params.accessToken}`, + }), + body: (params) => { + const body: Record = {} + + if (params.name) body.name = params.name + if (params.description) body.description = params.description + if (params.slug) body.slug = params.slug + + return body + }, + }, + + transformResponse: async (response: Response) => { + if (!response.ok) { + const error = await response.json().catch(() => ({})) + throw new Error(error.message || `WordPress API error: ${response.status}`) + } + + const data = await response.json() + + return { + success: true, + output: { + tag: { + id: data.id, + count: data.count, + description: data.description, + link: data.link, + name: data.name, + slug: data.slug, + taxonomy: data.taxonomy, + }, + }, + } + }, + + outputs: { + tag: { + type: 'object', + description: 'The updated tag', + properties: { + id: { type: 'number', description: 'Tag ID' }, + count: { type: 'number', description: 'Number of posts with this tag' }, + description: { type: 'string', description: 'Tag description' }, + link: { type: 'string', description: 'Tag archive URL' }, + name: { type: 'string', description: 'Tag name' }, + slug: { type: 'string', description: 'Tag slug' }, + taxonomy: { type: 'string', description: 'Taxonomy name' }, + }, + }, + }, +}