chore: import upstream snapshot with attribution
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressCreateCategoryParams,
|
||||
type WordPressCreateCategoryResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const createCategoryTool: ToolConfig<
|
||||
WordPressCreateCategoryParams,
|
||||
WordPressCreateCategoryResponse
|
||||
> = {
|
||||
id: 'wordpress_create_category',
|
||||
name: 'WordPress Create Category',
|
||||
description: 'Create a new 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)',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
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`,
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {
|
||||
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 created 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' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressCreateCommentParams,
|
||||
type WordPressCreateCommentResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const createCommentTool: ToolConfig<
|
||||
WordPressCreateCommentParams,
|
||||
WordPressCreateCommentResponse
|
||||
> = {
|
||||
id: 'wordpress_create_comment',
|
||||
name: 'WordPress Create Comment',
|
||||
description: 'Create a new comment on a WordPress.com post',
|
||||
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)',
|
||||
},
|
||||
postId: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the post to comment on',
|
||||
},
|
||||
content: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comment content',
|
||||
},
|
||||
parent: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Parent comment ID for replies',
|
||||
},
|
||||
authorName: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Comment author display name',
|
||||
},
|
||||
authorEmail: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Comment author email',
|
||||
},
|
||||
authorUrl: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Comment author URL',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `${WORDPRESS_COM_API_BASE}/${params.siteId}/comments`,
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {
|
||||
post: params.postId,
|
||||
content: params.content,
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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: {
|
||||
comment: {
|
||||
id: data.id,
|
||||
post: data.post,
|
||||
parent: data.parent,
|
||||
author: data.author,
|
||||
author_name: data.author_name,
|
||||
author_email: data.author_email,
|
||||
author_url: data.author_url,
|
||||
date: data.date,
|
||||
content: data.content,
|
||||
link: data.link,
|
||||
status: data.status,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
comment: {
|
||||
type: 'object',
|
||||
description: 'The created comment',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'Comment ID' },
|
||||
post: { type: 'number', description: 'Post ID' },
|
||||
parent: { type: 'number', description: 'Parent comment ID' },
|
||||
author: { type: 'number', description: 'Author user ID' },
|
||||
author_name: { type: 'string', description: 'Author display name' },
|
||||
author_email: { type: 'string', description: 'Author email' },
|
||||
author_url: { type: 'string', description: 'Author URL' },
|
||||
date: { type: 'string', description: 'Comment date' },
|
||||
content: { type: 'object', description: 'Comment content object' },
|
||||
link: { type: 'string', description: 'Comment permalink' },
|
||||
status: { type: 'string', description: 'Comment status' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressCreatePageParams,
|
||||
type WordPressCreatePageResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const createPageTool: ToolConfig<WordPressCreatePageParams, WordPressCreatePageResponse> = {
|
||||
id: 'wordpress_create_page',
|
||||
name: 'WordPress Create Page',
|
||||
description: 'Create a new page 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)',
|
||||
},
|
||||
title: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page title',
|
||||
},
|
||||
content: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page content (HTML or plain text)',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page status: publish, draft, pending, private',
|
||||
},
|
||||
excerpt: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page excerpt',
|
||||
},
|
||||
parent: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Parent page ID for hierarchical pages',
|
||||
},
|
||||
menuOrder: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Order in page menu',
|
||||
},
|
||||
featuredMedia: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Featured image media ID',
|
||||
},
|
||||
slug: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'URL slug for the page',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `${WORDPRESS_COM_API_BASE}/${params.siteId}/pages`,
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {
|
||||
title: params.title,
|
||||
}
|
||||
|
||||
if (params.content) body.content = params.content
|
||||
if (params.status) body.status = params.status
|
||||
if (params.excerpt) body.excerpt = params.excerpt
|
||||
if (params.slug) body.slug = params.slug
|
||||
if (params.parent !== undefined) body.parent = params.parent
|
||||
if (params.menuOrder !== undefined) body.menu_order = params.menuOrder
|
||||
if (params.featuredMedia !== undefined) body.featured_media = params.featuredMedia
|
||||
|
||||
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: {
|
||||
page: {
|
||||
id: data.id,
|
||||
date: data.date,
|
||||
modified: data.modified,
|
||||
slug: data.slug,
|
||||
status: data.status,
|
||||
type: data.type,
|
||||
link: data.link,
|
||||
title: data.title,
|
||||
content: data.content,
|
||||
excerpt: data.excerpt,
|
||||
author: data.author,
|
||||
featured_media: data.featured_media,
|
||||
parent: data.parent,
|
||||
menu_order: data.menu_order,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
page: {
|
||||
type: 'object',
|
||||
description: 'The created page',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'Page ID' },
|
||||
date: { type: 'string', description: 'Page creation date' },
|
||||
modified: { type: 'string', description: 'Page modification date' },
|
||||
slug: { type: 'string', description: 'Page slug' },
|
||||
status: { type: 'string', description: 'Page status' },
|
||||
type: { type: 'string', description: 'Content type' },
|
||||
link: { type: 'string', description: 'Page URL' },
|
||||
title: { type: 'object', description: 'Page title object' },
|
||||
content: { type: 'object', description: 'Page content object' },
|
||||
excerpt: { type: 'object', description: 'Page excerpt object' },
|
||||
author: { type: 'number', description: 'Author ID' },
|
||||
featured_media: { type: 'number', description: 'Featured media ID' },
|
||||
parent: { type: 'number', description: 'Parent page ID' },
|
||||
menu_order: { type: 'number', description: 'Menu order' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressCreatePostParams,
|
||||
type WordPressCreatePostResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const createPostTool: ToolConfig<WordPressCreatePostParams, WordPressCreatePostResponse> = {
|
||||
id: 'wordpress_create_post',
|
||||
name: 'WordPress Create Post',
|
||||
description: 'Create a new blog post 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)',
|
||||
},
|
||||
title: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Post title',
|
||||
},
|
||||
content: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Post content (HTML or plain text)',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Post status: publish, draft, pending, private, or future',
|
||||
},
|
||||
excerpt: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Post excerpt',
|
||||
},
|
||||
categories: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated category IDs',
|
||||
},
|
||||
tags: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated tag IDs',
|
||||
},
|
||||
featuredMedia: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Featured image media ID',
|
||||
},
|
||||
slug: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'URL slug for the post',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `${WORDPRESS_COM_API_BASE}/${params.siteId}/posts`,
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {
|
||||
title: params.title,
|
||||
}
|
||||
|
||||
if (params.content) body.content = params.content
|
||||
if (params.status) body.status = params.status
|
||||
if (params.excerpt) body.excerpt = params.excerpt
|
||||
if (params.slug) body.slug = params.slug
|
||||
if (params.featuredMedia !== undefined) body.featured_media = params.featuredMedia
|
||||
|
||||
if (params.categories) {
|
||||
body.categories = params.categories
|
||||
.split(',')
|
||||
.map((id: string) => Number.parseInt(id.trim(), 10))
|
||||
.filter((id: number) => !Number.isNaN(id))
|
||||
}
|
||||
|
||||
if (params.tags) {
|
||||
body.tags = params.tags
|
||||
.split(',')
|
||||
.map((id: string) => Number.parseInt(id.trim(), 10))
|
||||
.filter((id: number) => !Number.isNaN(id))
|
||||
}
|
||||
|
||||
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: {
|
||||
post: {
|
||||
id: data.id,
|
||||
date: data.date,
|
||||
modified: data.modified,
|
||||
slug: data.slug,
|
||||
status: data.status,
|
||||
type: data.type,
|
||||
link: data.link,
|
||||
title: data.title,
|
||||
content: data.content,
|
||||
excerpt: data.excerpt,
|
||||
author: data.author,
|
||||
featured_media: data.featured_media,
|
||||
categories: data.categories || [],
|
||||
tags: data.tags || [],
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
post: {
|
||||
type: 'object',
|
||||
description: 'The created post',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'Post ID' },
|
||||
date: { type: 'string', description: 'Post creation date' },
|
||||
modified: { type: 'string', description: 'Post modification date' },
|
||||
slug: { type: 'string', description: 'Post slug' },
|
||||
status: { type: 'string', description: 'Post status' },
|
||||
type: { type: 'string', description: 'Post type' },
|
||||
link: { type: 'string', description: 'Post URL' },
|
||||
title: { type: 'object', description: 'Post title object' },
|
||||
content: { type: 'object', description: 'Post content object' },
|
||||
excerpt: { type: 'object', description: 'Post excerpt object' },
|
||||
author: { type: 'number', description: 'Author ID' },
|
||||
featured_media: { type: 'number', description: 'Featured media ID' },
|
||||
categories: { type: 'array', description: 'Category IDs' },
|
||||
tags: { type: 'array', description: 'Tag IDs' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressCreateTagParams,
|
||||
type WordPressCreateTagResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const createTagTool: ToolConfig<WordPressCreateTagParams, WordPressCreateTagResponse> = {
|
||||
id: 'wordpress_create_tag',
|
||||
name: 'WordPress Create Tag',
|
||||
description: 'Create a new 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)',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
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`,
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {
|
||||
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 created 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' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressDeleteCategoryParams,
|
||||
type WordPressDeleteCategoryResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const deleteCategoryTool: ToolConfig<
|
||||
WordPressDeleteCategoryParams,
|
||||
WordPressDeleteCategoryResponse
|
||||
> = {
|
||||
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' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressDeleteCommentParams,
|
||||
type WordPressDeleteCommentResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const deleteCommentTool: ToolConfig<
|
||||
WordPressDeleteCommentParams,
|
||||
WordPressDeleteCommentResponse
|
||||
> = {
|
||||
id: 'wordpress_delete_comment',
|
||||
name: 'WordPress Delete Comment',
|
||||
description: 'Delete a comment 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)',
|
||||
},
|
||||
commentId: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the comment to delete',
|
||||
},
|
||||
force: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Bypass trash and force delete permanently',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const forceParam = params.force ? '?force=true' : ''
|
||||
return `${WORDPRESS_COM_API_BASE}/${params.siteId}/comments/${params.commentId}${forceParam}`
|
||||
},
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
date: data.date || data.previous?.date,
|
||||
content: data.content || data.previous?.content,
|
||||
link: data.link || data.previous?.link,
|
||||
status: data.status || data.previous?.status || 'trash',
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
deleted: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the comment was deleted',
|
||||
},
|
||||
comment: {
|
||||
type: 'object',
|
||||
description: 'The deleted comment',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'Comment ID' },
|
||||
post: { type: 'number', description: 'Post ID' },
|
||||
parent: { type: 'number', description: 'Parent comment ID' },
|
||||
author: { type: 'number', description: 'Author user ID' },
|
||||
author_name: { type: 'string', description: 'Author display name' },
|
||||
author_email: { type: 'string', description: 'Author email' },
|
||||
author_url: { type: 'string', description: 'Author URL' },
|
||||
date: { type: 'string', description: 'Comment date' },
|
||||
content: { type: 'object', description: 'Comment content object' },
|
||||
link: { type: 'string', description: 'Comment permalink' },
|
||||
status: { type: 'string', description: 'Comment status' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressDeleteMediaParams,
|
||||
type WordPressDeleteMediaResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const deleteMediaTool: ToolConfig<WordPressDeleteMediaParams, WordPressDeleteMediaResponse> =
|
||||
{
|
||||
id: 'wordpress_delete_media',
|
||||
name: 'WordPress Delete Media',
|
||||
description: 'Delete a media item 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)',
|
||||
},
|
||||
mediaId: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the media item to delete',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
// 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',
|
||||
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,
|
||||
media: {
|
||||
id: data.id ?? data.previous?.id,
|
||||
date: data.date || data.previous?.date,
|
||||
slug: data.slug || data.previous?.slug,
|
||||
type: data.type || data.previous?.type,
|
||||
link: data.link || data.previous?.link,
|
||||
title: data.title || data.previous?.title,
|
||||
caption: data.caption || data.previous?.caption,
|
||||
alt_text: data.alt_text || data.previous?.alt_text,
|
||||
media_type: data.media_type || data.previous?.media_type,
|
||||
mime_type: data.mime_type || data.previous?.mime_type,
|
||||
source_url: data.source_url || data.previous?.source_url,
|
||||
media_details: data.media_details || data.previous?.media_details,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
deleted: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the media was deleted',
|
||||
},
|
||||
media: {
|
||||
type: 'object',
|
||||
description: 'The deleted media item',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'Media ID' },
|
||||
date: { type: 'string', description: 'Upload date' },
|
||||
slug: { type: 'string', description: 'Media slug' },
|
||||
type: { type: 'string', description: 'Content type' },
|
||||
link: { type: 'string', description: 'Media page URL' },
|
||||
title: { type: 'object', description: 'Media title object' },
|
||||
caption: { type: 'object', description: 'Media caption object' },
|
||||
alt_text: { type: 'string', description: 'Alt text' },
|
||||
media_type: { type: 'string', description: 'Media type (image, video, etc.)' },
|
||||
mime_type: { type: 'string', description: 'MIME type' },
|
||||
source_url: { type: 'string', description: 'Direct URL to the media file' },
|
||||
media_details: { type: 'object', description: 'Media details (dimensions, etc.)' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressDeletePageParams,
|
||||
type WordPressDeletePageResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const deletePageTool: ToolConfig<WordPressDeletePageParams, WordPressDeletePageResponse> = {
|
||||
id: 'wordpress_delete_page',
|
||||
name: 'WordPress Delete Page',
|
||||
description: 'Delete a page 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)',
|
||||
},
|
||||
pageId: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the page to delete',
|
||||
},
|
||||
force: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Bypass trash and force delete permanently',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const forceParam = params.force ? '?force=true' : ''
|
||||
return `${WORDPRESS_COM_API_BASE}/${params.siteId}/pages/${params.pageId}${forceParam}`
|
||||
},
|
||||
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,
|
||||
page: {
|
||||
id: data.id ?? data.previous?.id,
|
||||
date: data.date || data.previous?.date,
|
||||
modified: data.modified || data.previous?.modified,
|
||||
slug: data.slug || data.previous?.slug,
|
||||
status: data.status || data.previous?.status || 'trash',
|
||||
type: data.type || data.previous?.type,
|
||||
link: data.link || data.previous?.link,
|
||||
title: data.title || data.previous?.title,
|
||||
content: data.content || data.previous?.content,
|
||||
excerpt: data.excerpt || data.previous?.excerpt,
|
||||
author: data.author ?? data.previous?.author,
|
||||
featured_media: data.featured_media ?? data.previous?.featured_media,
|
||||
parent: data.parent ?? data.previous?.parent,
|
||||
menu_order: data.menu_order ?? data.previous?.menu_order,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
deleted: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the page was deleted',
|
||||
},
|
||||
page: {
|
||||
type: 'object',
|
||||
description: 'The deleted page',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'Page ID' },
|
||||
date: { type: 'string', description: 'Page creation date' },
|
||||
modified: { type: 'string', description: 'Page modification date' },
|
||||
slug: { type: 'string', description: 'Page slug' },
|
||||
status: { type: 'string', description: 'Page status' },
|
||||
type: { type: 'string', description: 'Content type' },
|
||||
link: { type: 'string', description: 'Page URL' },
|
||||
title: { type: 'object', description: 'Page title object' },
|
||||
content: { type: 'object', description: 'Page content object' },
|
||||
excerpt: { type: 'object', description: 'Page excerpt object' },
|
||||
author: { type: 'number', description: 'Author ID' },
|
||||
featured_media: { type: 'number', description: 'Featured media ID' },
|
||||
parent: { type: 'number', description: 'Parent page ID' },
|
||||
menu_order: { type: 'number', description: 'Menu order' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressDeletePostParams,
|
||||
type WordPressDeletePostResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const deletePostTool: ToolConfig<WordPressDeletePostParams, WordPressDeletePostResponse> = {
|
||||
id: 'wordpress_delete_post',
|
||||
name: 'WordPress Delete Post',
|
||||
description: 'Delete a blog post 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)',
|
||||
},
|
||||
postId: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the post to delete',
|
||||
},
|
||||
force: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Bypass trash and force delete permanently',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const forceParam = params.force ? '?force=true' : ''
|
||||
return `${WORDPRESS_COM_API_BASE}/${params.siteId}/posts/${params.postId}${forceParam}`
|
||||
},
|
||||
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,
|
||||
post: {
|
||||
id: data.id ?? data.previous?.id,
|
||||
date: data.date || data.previous?.date,
|
||||
modified: data.modified || data.previous?.modified,
|
||||
slug: data.slug || data.previous?.slug,
|
||||
status: data.status || data.previous?.status || 'trash',
|
||||
type: data.type || data.previous?.type,
|
||||
link: data.link || data.previous?.link,
|
||||
title: data.title || data.previous?.title,
|
||||
content: data.content || data.previous?.content,
|
||||
excerpt: data.excerpt || data.previous?.excerpt,
|
||||
author: data.author ?? data.previous?.author,
|
||||
featured_media: data.featured_media ?? data.previous?.featured_media,
|
||||
categories: data.categories || data.previous?.categories || [],
|
||||
tags: data.tags || data.previous?.tags || [],
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
deleted: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the post was deleted',
|
||||
},
|
||||
post: {
|
||||
type: 'object',
|
||||
description: 'The deleted post',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'Post ID' },
|
||||
date: { type: 'string', description: 'Post creation date' },
|
||||
modified: { type: 'string', description: 'Post modification date' },
|
||||
slug: { type: 'string', description: 'Post slug' },
|
||||
status: { type: 'string', description: 'Post status' },
|
||||
type: { type: 'string', description: 'Post type' },
|
||||
link: { type: 'string', description: 'Post URL' },
|
||||
title: { type: 'object', description: 'Post title object' },
|
||||
content: { type: 'object', description: 'Post content object' },
|
||||
excerpt: { type: 'object', description: 'Post excerpt object' },
|
||||
author: { type: 'number', description: 'Author ID' },
|
||||
featured_media: { type: 'number', description: 'Featured media ID' },
|
||||
categories: { type: 'array', description: 'Category IDs' },
|
||||
tags: { type: 'array', description: 'Tag IDs' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressDeleteTagParams,
|
||||
type WordPressDeleteTagResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const deleteTagTool: ToolConfig<WordPressDeleteTagParams, WordPressDeleteTagResponse> = {
|
||||
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' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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<WordPressGetCategoryParams, WordPressGetCategoryResponse> =
|
||||
{
|
||||
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' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressGetCurrentUserParams,
|
||||
type WordPressGetCurrentUserResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const getCurrentUserTool: ToolConfig<
|
||||
WordPressGetCurrentUserParams,
|
||||
WordPressGetCurrentUserResponse
|
||||
> = {
|
||||
id: 'wordpress_get_current_user',
|
||||
name: 'WordPress Get Current User',
|
||||
description: 'Get information about the currently authenticated WordPress.com user',
|
||||
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)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `${WORDPRESS_COM_API_BASE}/${params.siteId}/users/me`,
|
||||
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: {
|
||||
user: {
|
||||
id: data.id,
|
||||
username: data.username,
|
||||
name: data.name,
|
||||
first_name: data.first_name,
|
||||
last_name: data.last_name,
|
||||
email: data.email,
|
||||
url: data.url,
|
||||
description: data.description,
|
||||
link: data.link,
|
||||
slug: data.slug,
|
||||
roles: data.roles || [],
|
||||
avatar_urls: data.avatar_urls,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
user: {
|
||||
type: 'object',
|
||||
description: 'The current user',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'User ID' },
|
||||
username: { type: 'string', description: 'Username' },
|
||||
name: { type: 'string', description: 'Display name' },
|
||||
first_name: { type: 'string', description: 'First name' },
|
||||
last_name: { type: 'string', description: 'Last name' },
|
||||
email: { type: 'string', description: 'Email address' },
|
||||
url: { type: 'string', description: 'User website URL' },
|
||||
description: { type: 'string', description: 'User bio' },
|
||||
link: { type: 'string', description: 'Author archive URL' },
|
||||
slug: { type: 'string', description: 'User slug' },
|
||||
roles: { type: 'array', description: 'User roles' },
|
||||
avatar_urls: { type: 'object', description: 'Avatar URLs at different sizes' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressGetMediaParams,
|
||||
type WordPressGetMediaResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const getMediaTool: ToolConfig<WordPressGetMediaParams, WordPressGetMediaResponse> = {
|
||||
id: 'wordpress_get_media',
|
||||
name: 'WordPress Get Media',
|
||||
description: 'Get a single media item 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)',
|
||||
},
|
||||
mediaId: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the media item to retrieve',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `${WORDPRESS_COM_API_BASE}/${params.siteId}/media/${params.mediaId}`,
|
||||
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: {
|
||||
media: {
|
||||
id: data.id,
|
||||
date: data.date,
|
||||
slug: data.slug,
|
||||
type: data.type,
|
||||
link: data.link,
|
||||
title: data.title,
|
||||
caption: data.caption,
|
||||
alt_text: data.alt_text,
|
||||
media_type: data.media_type,
|
||||
mime_type: data.mime_type,
|
||||
source_url: data.source_url,
|
||||
media_details: data.media_details,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
media: {
|
||||
type: 'object',
|
||||
description: 'The retrieved media item',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'Media ID' },
|
||||
date: { type: 'string', description: 'Upload date' },
|
||||
slug: { type: 'string', description: 'Media slug' },
|
||||
type: { type: 'string', description: 'Content type' },
|
||||
link: { type: 'string', description: 'Media page URL' },
|
||||
title: { type: 'object', description: 'Media title object' },
|
||||
caption: { type: 'object', description: 'Media caption object' },
|
||||
alt_text: { type: 'string', description: 'Alt text' },
|
||||
media_type: { type: 'string', description: 'Media type (image, video, etc.)' },
|
||||
mime_type: { type: 'string', description: 'MIME type' },
|
||||
source_url: { type: 'string', description: 'Direct URL to the media file' },
|
||||
media_details: { type: 'object', description: 'Media details (dimensions, etc.)' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressGetPageParams,
|
||||
type WordPressGetPageResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const getPageTool: ToolConfig<WordPressGetPageParams, WordPressGetPageResponse> = {
|
||||
id: 'wordpress_get_page',
|
||||
name: 'WordPress Get Page',
|
||||
description: 'Get a single page 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)',
|
||||
},
|
||||
pageId: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the page to retrieve',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `${WORDPRESS_COM_API_BASE}/${params.siteId}/pages/${params.pageId}`,
|
||||
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: {
|
||||
page: {
|
||||
id: data.id,
|
||||
date: data.date,
|
||||
modified: data.modified,
|
||||
slug: data.slug,
|
||||
status: data.status,
|
||||
type: data.type,
|
||||
link: data.link,
|
||||
title: data.title,
|
||||
content: data.content,
|
||||
excerpt: data.excerpt,
|
||||
author: data.author,
|
||||
featured_media: data.featured_media,
|
||||
parent: data.parent,
|
||||
menu_order: data.menu_order,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
page: {
|
||||
type: 'object',
|
||||
description: 'The retrieved page',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'Page ID' },
|
||||
date: { type: 'string', description: 'Page creation date' },
|
||||
modified: { type: 'string', description: 'Page modification date' },
|
||||
slug: { type: 'string', description: 'Page slug' },
|
||||
status: { type: 'string', description: 'Page status' },
|
||||
type: { type: 'string', description: 'Content type' },
|
||||
link: { type: 'string', description: 'Page URL' },
|
||||
title: { type: 'object', description: 'Page title object' },
|
||||
content: { type: 'object', description: 'Page content object' },
|
||||
excerpt: { type: 'object', description: 'Page excerpt object' },
|
||||
author: { type: 'number', description: 'Author ID' },
|
||||
featured_media: { type: 'number', description: 'Featured media ID' },
|
||||
parent: { type: 'number', description: 'Parent page ID' },
|
||||
menu_order: { type: 'number', description: 'Menu order' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressGetPostParams,
|
||||
type WordPressGetPostResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const getPostTool: ToolConfig<WordPressGetPostParams, WordPressGetPostResponse> = {
|
||||
id: 'wordpress_get_post',
|
||||
name: 'WordPress Get Post',
|
||||
description: 'Get a single blog post 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)',
|
||||
},
|
||||
postId: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the post to retrieve',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `${WORDPRESS_COM_API_BASE}/${params.siteId}/posts/${params.postId}`,
|
||||
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: {
|
||||
post: {
|
||||
id: data.id,
|
||||
date: data.date,
|
||||
modified: data.modified,
|
||||
slug: data.slug,
|
||||
status: data.status,
|
||||
type: data.type,
|
||||
link: data.link,
|
||||
title: data.title,
|
||||
content: data.content,
|
||||
excerpt: data.excerpt,
|
||||
author: data.author,
|
||||
featured_media: data.featured_media,
|
||||
categories: data.categories || [],
|
||||
tags: data.tags || [],
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
post: {
|
||||
type: 'object',
|
||||
description: 'The retrieved post',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'Post ID' },
|
||||
date: { type: 'string', description: 'Post creation date' },
|
||||
modified: { type: 'string', description: 'Post modification date' },
|
||||
slug: { type: 'string', description: 'Post slug' },
|
||||
status: { type: 'string', description: 'Post status' },
|
||||
type: { type: 'string', description: 'Post type' },
|
||||
link: { type: 'string', description: 'Post URL' },
|
||||
title: { type: 'object', description: 'Post title object' },
|
||||
content: { type: 'object', description: 'Post content object' },
|
||||
excerpt: { type: 'object', description: 'Post excerpt object' },
|
||||
author: { type: 'number', description: 'Author ID' },
|
||||
featured_media: { type: 'number', description: 'Featured media ID' },
|
||||
categories: { type: 'array', description: 'Category IDs' },
|
||||
tags: { type: 'array', description: 'Tag IDs' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -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<WordPressGetTagParams, WordPressGetTagResponse> = {
|
||||
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' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressGetUserParams,
|
||||
type WordPressGetUserResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const getUserTool: ToolConfig<WordPressGetUserParams, WordPressGetUserResponse> = {
|
||||
id: 'wordpress_get_user',
|
||||
name: 'WordPress Get User',
|
||||
description: 'Get a specific user 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)',
|
||||
},
|
||||
userId: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the user to retrieve',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `${WORDPRESS_COM_API_BASE}/${params.siteId}/users/${params.userId}`,
|
||||
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: {
|
||||
user: {
|
||||
id: data.id,
|
||||
username: data.username,
|
||||
name: data.name,
|
||||
first_name: data.first_name,
|
||||
last_name: data.last_name,
|
||||
email: data.email,
|
||||
url: data.url,
|
||||
description: data.description,
|
||||
link: data.link,
|
||||
slug: data.slug,
|
||||
roles: data.roles || [],
|
||||
avatar_urls: data.avatar_urls,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
user: {
|
||||
type: 'object',
|
||||
description: 'The retrieved user',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'User ID' },
|
||||
username: { type: 'string', description: 'Username' },
|
||||
name: { type: 'string', description: 'Display name' },
|
||||
first_name: { type: 'string', description: 'First name' },
|
||||
last_name: { type: 'string', description: 'Last name' },
|
||||
email: { type: 'string', description: 'Email address' },
|
||||
url: { type: 'string', description: 'User website URL' },
|
||||
description: { type: 'string', description: 'User bio' },
|
||||
link: { type: 'string', description: 'Author archive URL' },
|
||||
slug: { type: 'string', description: 'User slug' },
|
||||
roles: { type: 'array', description: 'User roles' },
|
||||
avatar_urls: { type: 'object', description: 'Avatar URLs at different sizes' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
// WordPress tools exports
|
||||
import { createCategoryTool } from '@/tools/wordpress/create_category'
|
||||
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'
|
||||
import { listMediaTool } from '@/tools/wordpress/list_media'
|
||||
import { listPagesTool } from '@/tools/wordpress/list_pages'
|
||||
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
|
||||
export const wordpressCreatePostTool = createPostTool
|
||||
export const wordpressUpdatePostTool = updatePostTool
|
||||
export const wordpressDeletePostTool = deletePostTool
|
||||
export const wordpressGetPostTool = getPostTool
|
||||
export const wordpressListPostsTool = listPostsTool
|
||||
|
||||
// Page operations
|
||||
export const wordpressCreatePageTool = createPageTool
|
||||
export const wordpressUpdatePageTool = updatePageTool
|
||||
export const wordpressDeletePageTool = deletePageTool
|
||||
export const wordpressGetPageTool = getPageTool
|
||||
export const wordpressListPagesTool = listPagesTool
|
||||
|
||||
// Media operations
|
||||
export const wordpressUploadMediaTool = uploadMediaTool
|
||||
export const wordpressGetMediaTool = getMediaTool
|
||||
export const wordpressListMediaTool = listMediaTool
|
||||
export const wordpressDeleteMediaTool = deleteMediaTool
|
||||
|
||||
// Comment operations
|
||||
export const wordpressCreateCommentTool = createCommentTool
|
||||
export const wordpressListCommentsTool = listCommentsTool
|
||||
export const wordpressUpdateCommentTool = updateCommentTool
|
||||
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
|
||||
export const wordpressListUsersTool = listUsersTool
|
||||
export const wordpressGetUserTool = getUserTool
|
||||
|
||||
// Search operations
|
||||
export const wordpressSearchContentTool = searchContentTool
|
||||
@@ -0,0 +1,131 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressListCategoriesParams,
|
||||
type WordPressListCategoriesResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const listCategoriesTool: ToolConfig<
|
||||
WordPressListCategoriesParams,
|
||||
WordPressListCategoriesResponse
|
||||
> = {
|
||||
id: 'wordpress_list_categories',
|
||||
name: 'WordPress List Categories',
|
||||
description: 'List categories 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)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of categories per request (e.g., 10, 25, 50). Default: 10, max: 100',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (e.g., 1, 2, 3)',
|
||||
},
|
||||
search: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Search term to filter categories (e.g., "news", "technology")',
|
||||
},
|
||||
order: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Order direction: asc or desc',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.perPage) queryParams.append('per_page', String(params.perPage))
|
||||
if (params.page) queryParams.append('page', String(params.page))
|
||||
if (params.search) queryParams.append('search', params.search)
|
||||
if (params.order) queryParams.append('order', params.order)
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return `${WORDPRESS_COM_API_BASE}/${params.siteId}/categories${queryString ? `?${queryString}` : ''}`
|
||||
},
|
||||
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()
|
||||
const total = Number.parseInt(response.headers.get('X-WP-Total') || '0', 10)
|
||||
const totalPages = Number.parseInt(response.headers.get('X-WP-TotalPages') || '0', 10)
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
categories: data.map((cat: any) => ({
|
||||
id: cat.id,
|
||||
count: cat.count,
|
||||
description: cat.description,
|
||||
link: cat.link,
|
||||
name: cat.name,
|
||||
slug: cat.slug,
|
||||
taxonomy: cat.taxonomy,
|
||||
parent: cat.parent,
|
||||
})),
|
||||
total,
|
||||
totalPages,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
categories: {
|
||||
type: 'array',
|
||||
description: 'List of categories',
|
||||
items: {
|
||||
type: 'object',
|
||||
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' },
|
||||
},
|
||||
},
|
||||
},
|
||||
total: {
|
||||
type: 'number',
|
||||
description: 'Total number of categories',
|
||||
},
|
||||
totalPages: {
|
||||
type: 'number',
|
||||
description: 'Total number of result pages',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressListCommentsParams,
|
||||
type WordPressListCommentsResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const listCommentsTool: ToolConfig<
|
||||
WordPressListCommentsParams,
|
||||
WordPressListCommentsResponse
|
||||
> = {
|
||||
id: 'wordpress_list_comments',
|
||||
name: 'WordPress List Comments',
|
||||
description: 'List comments from WordPress.com with optional filters',
|
||||
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)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of comments per request (e.g., 10, 25, 50). Default: 10, max: 100',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (e.g., 1, 2, 3)',
|
||||
},
|
||||
postId: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter by post ID (e.g., 123, 456)',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter by comment status: approved, hold, spam, trash',
|
||||
},
|
||||
search: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Search term to filter comments (e.g., "question", "feedback")',
|
||||
},
|
||||
orderBy: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Order by field: date, id, parent',
|
||||
},
|
||||
order: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Order direction: asc or desc',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.perPage) queryParams.append('per_page', String(params.perPage))
|
||||
if (params.page) queryParams.append('page', String(params.page))
|
||||
if (params.postId) queryParams.append('post', String(params.postId))
|
||||
if (params.status) queryParams.append('status', params.status)
|
||||
if (params.search) queryParams.append('search', params.search)
|
||||
if (params.orderBy) queryParams.append('orderby', params.orderBy)
|
||||
if (params.order) queryParams.append('order', params.order)
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return `${WORDPRESS_COM_API_BASE}/${params.siteId}/comments${queryString ? `?${queryString}` : ''}`
|
||||
},
|
||||
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()
|
||||
const total = Number.parseInt(response.headers.get('X-WP-Total') || '0', 10)
|
||||
const totalPages = Number.parseInt(response.headers.get('X-WP-TotalPages') || '0', 10)
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
comments: data.map((comment: any) => ({
|
||||
id: comment.id,
|
||||
post: comment.post,
|
||||
parent: comment.parent,
|
||||
author: comment.author,
|
||||
author_name: comment.author_name,
|
||||
author_email: comment.author_email,
|
||||
author_url: comment.author_url,
|
||||
date: comment.date,
|
||||
content: comment.content,
|
||||
link: comment.link,
|
||||
status: comment.status,
|
||||
})),
|
||||
total,
|
||||
totalPages,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
comments: {
|
||||
type: 'array',
|
||||
description: 'List of comments',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'Comment ID' },
|
||||
post: { type: 'number', description: 'Post ID' },
|
||||
parent: { type: 'number', description: 'Parent comment ID' },
|
||||
author: { type: 'number', description: 'Author user ID' },
|
||||
author_name: { type: 'string', description: 'Author display name' },
|
||||
author_email: { type: 'string', description: 'Author email' },
|
||||
author_url: { type: 'string', description: 'Author URL' },
|
||||
date: { type: 'string', description: 'Comment date' },
|
||||
content: { type: 'object', description: 'Comment content object' },
|
||||
link: { type: 'string', description: 'Comment permalink' },
|
||||
status: { type: 'string', description: 'Comment status' },
|
||||
},
|
||||
},
|
||||
},
|
||||
total: {
|
||||
type: 'number',
|
||||
description: 'Total number of comments',
|
||||
},
|
||||
totalPages: {
|
||||
type: 'number',
|
||||
description: 'Total number of result pages',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressListMediaParams,
|
||||
type WordPressListMediaResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const listMediaTool: ToolConfig<WordPressListMediaParams, WordPressListMediaResponse> = {
|
||||
id: 'wordpress_list_media',
|
||||
name: 'WordPress List Media',
|
||||
description: 'List media items from the WordPress.com media library',
|
||||
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)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of media items per request (e.g., 10, 25, 50). Default: 10, max: 100',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (e.g., 1, 2, 3)',
|
||||
},
|
||||
search: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Search term to filter media (e.g., "logo", "banner")',
|
||||
},
|
||||
mediaType: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter by media type: image, video, audio, application',
|
||||
},
|
||||
mimeType: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter by specific MIME type (e.g., image/jpeg, image/png)',
|
||||
},
|
||||
orderBy: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Order by field: date, id, title, slug',
|
||||
},
|
||||
order: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Order direction: asc or desc',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.perPage) queryParams.append('per_page', String(params.perPage))
|
||||
if (params.page) queryParams.append('page', String(params.page))
|
||||
if (params.search) queryParams.append('search', params.search)
|
||||
if (params.mediaType) queryParams.append('media_type', params.mediaType)
|
||||
if (params.mimeType) queryParams.append('mime_type', params.mimeType)
|
||||
if (params.orderBy) queryParams.append('orderby', params.orderBy)
|
||||
if (params.order) queryParams.append('order', params.order)
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return `${WORDPRESS_COM_API_BASE}/${params.siteId}/media${queryString ? `?${queryString}` : ''}`
|
||||
},
|
||||
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()
|
||||
const total = Number.parseInt(response.headers.get('X-WP-Total') || '0', 10)
|
||||
const totalPages = Number.parseInt(response.headers.get('X-WP-TotalPages') || '0', 10)
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
media: data.map((item: any) => ({
|
||||
id: item.id,
|
||||
date: item.date,
|
||||
slug: item.slug,
|
||||
type: item.type,
|
||||
link: item.link,
|
||||
title: item.title,
|
||||
caption: item.caption,
|
||||
alt_text: item.alt_text,
|
||||
media_type: item.media_type,
|
||||
mime_type: item.mime_type,
|
||||
source_url: item.source_url,
|
||||
media_details: item.media_details,
|
||||
})),
|
||||
total,
|
||||
totalPages,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
media: {
|
||||
type: 'array',
|
||||
description: 'List of media items',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'Media ID' },
|
||||
date: { type: 'string', description: 'Upload date' },
|
||||
slug: { type: 'string', description: 'Media slug' },
|
||||
type: { type: 'string', description: 'Content type' },
|
||||
link: { type: 'string', description: 'Media page URL' },
|
||||
title: { type: 'object', description: 'Media title object' },
|
||||
caption: { type: 'object', description: 'Media caption object' },
|
||||
alt_text: { type: 'string', description: 'Alt text' },
|
||||
media_type: { type: 'string', description: 'Media type (image, video, etc.)' },
|
||||
mime_type: { type: 'string', description: 'MIME type' },
|
||||
source_url: { type: 'string', description: 'Direct URL to the media file' },
|
||||
media_details: { type: 'object', description: 'Media details (dimensions, etc.)' },
|
||||
},
|
||||
},
|
||||
},
|
||||
total: {
|
||||
type: 'number',
|
||||
description: 'Total number of media items',
|
||||
},
|
||||
totalPages: {
|
||||
type: 'number',
|
||||
description: 'Total number of result pages',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressListPagesParams,
|
||||
type WordPressListPagesResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const listPagesTool: ToolConfig<WordPressListPagesParams, WordPressListPagesResponse> = {
|
||||
id: 'wordpress_list_pages',
|
||||
name: 'WordPress List Pages',
|
||||
description: 'List pages from WordPress.com with optional filters',
|
||||
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)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of pages per request (e.g., 10, 25, 50). Default: 10, max: 100',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (e.g., 1, 2, 3)',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page status filter: publish, draft, pending, private',
|
||||
},
|
||||
parent: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter by parent page ID (e.g., 123)',
|
||||
},
|
||||
search: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Search term to filter pages (e.g., "about", "contact")',
|
||||
},
|
||||
orderBy: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Order by field: date, id, title, slug, modified, menu_order',
|
||||
},
|
||||
order: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Order direction: asc or desc',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.perPage) queryParams.append('per_page', String(params.perPage))
|
||||
if (params.page) queryParams.append('page', String(params.page))
|
||||
if (params.status) queryParams.append('status', params.status)
|
||||
if (params.parent !== undefined) queryParams.append('parent', String(params.parent))
|
||||
if (params.search) queryParams.append('search', params.search)
|
||||
if (params.orderBy) queryParams.append('orderby', params.orderBy)
|
||||
if (params.order) queryParams.append('order', params.order)
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return `${WORDPRESS_COM_API_BASE}/${params.siteId}/pages${queryString ? `?${queryString}` : ''}`
|
||||
},
|
||||
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()
|
||||
const total = Number.parseInt(response.headers.get('X-WP-Total') || '0', 10)
|
||||
const totalPages = Number.parseInt(response.headers.get('X-WP-TotalPages') || '0', 10)
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
pages: data.map((page: any) => ({
|
||||
id: page.id,
|
||||
date: page.date,
|
||||
modified: page.modified,
|
||||
slug: page.slug,
|
||||
status: page.status,
|
||||
type: page.type,
|
||||
link: page.link,
|
||||
title: page.title,
|
||||
content: page.content,
|
||||
excerpt: page.excerpt,
|
||||
author: page.author,
|
||||
featured_media: page.featured_media,
|
||||
parent: page.parent,
|
||||
menu_order: page.menu_order,
|
||||
})),
|
||||
total,
|
||||
totalPages,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
pages: {
|
||||
type: 'array',
|
||||
description: 'List of pages',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'Page ID' },
|
||||
date: { type: 'string', description: 'Page creation date' },
|
||||
modified: { type: 'string', description: 'Page modification date' },
|
||||
slug: { type: 'string', description: 'Page slug' },
|
||||
status: { type: 'string', description: 'Page status' },
|
||||
type: { type: 'string', description: 'Content type' },
|
||||
link: { type: 'string', description: 'Page URL' },
|
||||
title: { type: 'object', description: 'Page title object' },
|
||||
content: { type: 'object', description: 'Page content object' },
|
||||
excerpt: { type: 'object', description: 'Page excerpt object' },
|
||||
author: { type: 'number', description: 'Author ID' },
|
||||
featured_media: { type: 'number', description: 'Featured media ID' },
|
||||
parent: { type: 'number', description: 'Parent page ID' },
|
||||
menu_order: { type: 'number', description: 'Menu order' },
|
||||
},
|
||||
},
|
||||
},
|
||||
total: {
|
||||
type: 'number',
|
||||
description: 'Total number of pages',
|
||||
},
|
||||
totalPages: {
|
||||
type: 'number',
|
||||
description: 'Total number of result pages',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressListPostsParams,
|
||||
type WordPressListPostsResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const listPostsTool: ToolConfig<WordPressListPostsParams, WordPressListPostsResponse> = {
|
||||
id: 'wordpress_list_posts',
|
||||
name: 'WordPress List Posts',
|
||||
description: 'List blog posts from WordPress.com with optional filters',
|
||||
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)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of posts per page (e.g., 10, 25, 50). Default: 10, max: 100',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (e.g., 1, 2, 3)',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Post status filter: publish, draft, pending, private',
|
||||
},
|
||||
author: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter by author ID (e.g., 1, 42)',
|
||||
},
|
||||
categories: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated category IDs to filter by (e.g., "1,2,3")',
|
||||
},
|
||||
tags: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated tag IDs to filter by (e.g., "5,10,15")',
|
||||
},
|
||||
search: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Search term to filter posts (e.g., "tutorial", "announcement")',
|
||||
},
|
||||
orderBy: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Order by field: date, id, title, slug, modified',
|
||||
},
|
||||
order: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Order direction: asc or desc',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.perPage) queryParams.append('per_page', String(params.perPage))
|
||||
if (params.page) queryParams.append('page', String(params.page))
|
||||
if (params.status) queryParams.append('status', params.status)
|
||||
if (params.author) queryParams.append('author', String(params.author))
|
||||
if (params.search) queryParams.append('search', params.search)
|
||||
if (params.orderBy) queryParams.append('orderby', params.orderBy)
|
||||
if (params.order) queryParams.append('order', params.order)
|
||||
|
||||
if (params.categories) {
|
||||
const catIds = params.categories
|
||||
.split(',')
|
||||
.map((id: string) => id.trim())
|
||||
.filter((id: string) => id.length > 0)
|
||||
queryParams.append('categories', catIds.join(','))
|
||||
}
|
||||
|
||||
if (params.tags) {
|
||||
const tagIds = params.tags
|
||||
.split(',')
|
||||
.map((id: string) => id.trim())
|
||||
.filter((id: string) => id.length > 0)
|
||||
queryParams.append('tags', tagIds.join(','))
|
||||
}
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return `${WORDPRESS_COM_API_BASE}/${params.siteId}/posts${queryString ? `?${queryString}` : ''}`
|
||||
},
|
||||
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()
|
||||
const total = Number.parseInt(response.headers.get('X-WP-Total') || '0', 10)
|
||||
const totalPages = Number.parseInt(response.headers.get('X-WP-TotalPages') || '0', 10)
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
posts: data.map((post: any) => ({
|
||||
id: post.id,
|
||||
date: post.date,
|
||||
modified: post.modified,
|
||||
slug: post.slug,
|
||||
status: post.status,
|
||||
type: post.type,
|
||||
link: post.link,
|
||||
title: post.title,
|
||||
content: post.content,
|
||||
excerpt: post.excerpt,
|
||||
author: post.author,
|
||||
featured_media: post.featured_media,
|
||||
categories: post.categories || [],
|
||||
tags: post.tags || [],
|
||||
})),
|
||||
total,
|
||||
totalPages,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
posts: {
|
||||
type: 'array',
|
||||
description: 'List of posts',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'Post ID' },
|
||||
date: { type: 'string', description: 'Post creation date' },
|
||||
modified: { type: 'string', description: 'Post modification date' },
|
||||
slug: { type: 'string', description: 'Post slug' },
|
||||
status: { type: 'string', description: 'Post status' },
|
||||
type: { type: 'string', description: 'Post type' },
|
||||
link: { type: 'string', description: 'Post URL' },
|
||||
title: { type: 'object', description: 'Post title object' },
|
||||
content: { type: 'object', description: 'Post content object' },
|
||||
excerpt: { type: 'object', description: 'Post excerpt object' },
|
||||
author: { type: 'number', description: 'Author ID' },
|
||||
featured_media: { type: 'number', description: 'Featured media ID' },
|
||||
categories: { type: 'array', description: 'Category IDs' },
|
||||
tags: { type: 'array', description: 'Tag IDs' },
|
||||
},
|
||||
},
|
||||
},
|
||||
total: {
|
||||
type: 'number',
|
||||
description: 'Total number of posts',
|
||||
},
|
||||
totalPages: {
|
||||
type: 'number',
|
||||
description: 'Total number of pages',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressListTagsParams,
|
||||
type WordPressListTagsResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const listTagsTool: ToolConfig<WordPressListTagsParams, WordPressListTagsResponse> = {
|
||||
id: 'wordpress_list_tags',
|
||||
name: 'WordPress List Tags',
|
||||
description: 'List tags 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)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of tags per request (e.g., 10, 25, 50). Default: 10, max: 100',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (e.g., 1, 2, 3)',
|
||||
},
|
||||
search: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Search term to filter tags (e.g., "javascript", "tutorial")',
|
||||
},
|
||||
order: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Order direction: asc or desc',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.perPage) queryParams.append('per_page', String(params.perPage))
|
||||
if (params.page) queryParams.append('page', String(params.page))
|
||||
if (params.search) queryParams.append('search', params.search)
|
||||
if (params.order) queryParams.append('order', params.order)
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return `${WORDPRESS_COM_API_BASE}/${params.siteId}/tags${queryString ? `?${queryString}` : ''}`
|
||||
},
|
||||
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()
|
||||
const total = Number.parseInt(response.headers.get('X-WP-Total') || '0', 10)
|
||||
const totalPages = Number.parseInt(response.headers.get('X-WP-TotalPages') || '0', 10)
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
tags: data.map((tag: any) => ({
|
||||
id: tag.id,
|
||||
count: tag.count,
|
||||
description: tag.description,
|
||||
link: tag.link,
|
||||
name: tag.name,
|
||||
slug: tag.slug,
|
||||
taxonomy: tag.taxonomy,
|
||||
})),
|
||||
total,
|
||||
totalPages,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
tags: {
|
||||
type: 'array',
|
||||
description: 'List of tags',
|
||||
items: {
|
||||
type: 'object',
|
||||
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' },
|
||||
},
|
||||
},
|
||||
},
|
||||
total: {
|
||||
type: 'number',
|
||||
description: 'Total number of tags',
|
||||
},
|
||||
totalPages: {
|
||||
type: 'number',
|
||||
description: 'Total number of result pages',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressListUsersParams,
|
||||
type WordPressListUsersResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const listUsersTool: ToolConfig<WordPressListUsersParams, WordPressListUsersResponse> = {
|
||||
id: 'wordpress_list_users',
|
||||
name: 'WordPress List Users',
|
||||
description: 'List users from WordPress.com (requires admin privileges)',
|
||||
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)',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of users per request (e.g., 10, 25, 50). Default: 10, max: 100',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination (e.g., 1, 2, 3)',
|
||||
},
|
||||
search: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Search term to filter users (e.g., "john", "admin")',
|
||||
},
|
||||
roles: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated role names to filter by (e.g., "administrator,editor")',
|
||||
},
|
||||
order: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Order direction: asc or desc',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.perPage) queryParams.append('per_page', String(params.perPage))
|
||||
if (params.page) queryParams.append('page', String(params.page))
|
||||
if (params.search) queryParams.append('search', params.search)
|
||||
if (params.roles) queryParams.append('roles', params.roles)
|
||||
if (params.order) queryParams.append('order', params.order)
|
||||
|
||||
const queryString = queryParams.toString()
|
||||
return `${WORDPRESS_COM_API_BASE}/${params.siteId}/users${queryString ? `?${queryString}` : ''}`
|
||||
},
|
||||
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()
|
||||
const total = Number.parseInt(response.headers.get('X-WP-Total') || '0', 10)
|
||||
const totalPages = Number.parseInt(response.headers.get('X-WP-TotalPages') || '0', 10)
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
users: data.map((user: any) => ({
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
name: user.name,
|
||||
first_name: user.first_name,
|
||||
last_name: user.last_name,
|
||||
email: user.email,
|
||||
url: user.url,
|
||||
description: user.description,
|
||||
link: user.link,
|
||||
slug: user.slug,
|
||||
roles: user.roles || [],
|
||||
avatar_urls: user.avatar_urls,
|
||||
})),
|
||||
total,
|
||||
totalPages,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
users: {
|
||||
type: 'array',
|
||||
description: 'List of users',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'User ID' },
|
||||
username: { type: 'string', description: 'Username' },
|
||||
name: { type: 'string', description: 'Display name' },
|
||||
first_name: { type: 'string', description: 'First name' },
|
||||
last_name: { type: 'string', description: 'Last name' },
|
||||
email: { type: 'string', description: 'Email address' },
|
||||
url: { type: 'string', description: 'User website URL' },
|
||||
description: { type: 'string', description: 'User bio' },
|
||||
link: { type: 'string', description: 'Author archive URL' },
|
||||
slug: { type: 'string', description: 'User slug' },
|
||||
roles: { type: 'array', description: 'User roles' },
|
||||
avatar_urls: { type: 'object', description: 'Avatar URLs at different sizes' },
|
||||
},
|
||||
},
|
||||
},
|
||||
total: {
|
||||
type: 'number',
|
||||
description: 'Total number of users',
|
||||
},
|
||||
totalPages: {
|
||||
type: 'number',
|
||||
description: 'Total number of result pages',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressSearchContentParams,
|
||||
type WordPressSearchContentResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const searchContentTool: ToolConfig<
|
||||
WordPressSearchContentParams,
|
||||
WordPressSearchContentResponse
|
||||
> = {
|
||||
id: 'wordpress_search_content',
|
||||
name: 'WordPress Search Content',
|
||||
description: 'Search across all content types in WordPress.com (posts, pages, media)',
|
||||
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)',
|
||||
},
|
||||
query: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Search query',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per request (default: 10, max: 100)',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination',
|
||||
},
|
||||
type: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Filter by search index type: post, term, or post-format',
|
||||
},
|
||||
subtype: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description:
|
||||
'Filter by subtype within the selected type (e.g., post or page when type is post)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
queryParams.append('search', params.query)
|
||||
if (params.perPage) queryParams.append('per_page', String(params.perPage))
|
||||
if (params.page) queryParams.append('page', String(params.page))
|
||||
if (params.type) queryParams.append('type', params.type)
|
||||
if (params.subtype) queryParams.append('subtype', params.subtype)
|
||||
|
||||
return `${WORDPRESS_COM_API_BASE}/${params.siteId}/search?${queryParams.toString()}`
|
||||
},
|
||||
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()
|
||||
const total = Number.parseInt(response.headers.get('X-WP-Total') || '0', 10)
|
||||
const totalPages = Number.parseInt(response.headers.get('X-WP-TotalPages') || '0', 10)
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
results: data.map((result: any) => ({
|
||||
id: result.id,
|
||||
title: result.title,
|
||||
url: result.url,
|
||||
type: result.type,
|
||||
subtype: result.subtype,
|
||||
})),
|
||||
total,
|
||||
totalPages,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
results: {
|
||||
type: 'array',
|
||||
description: 'Search results',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
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, term, or post-format)' },
|
||||
subtype: {
|
||||
type: 'string',
|
||||
description: 'Subtype within the content type (e.g., post, page)',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
total: {
|
||||
type: 'number',
|
||||
description: 'Total number of results',
|
||||
},
|
||||
totalPages: {
|
||||
type: 'number',
|
||||
description: 'Total number of result pages',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,708 @@
|
||||
// Common types for WordPress REST API tools
|
||||
import type { UserFile } from '@/executor/types'
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
// Common parameters for all WordPress tools (WordPress.com OAuth)
|
||||
// Note: accessToken is injected by the OAuth system at runtime, not defined in tool params
|
||||
interface WordPressBaseParams {
|
||||
siteId: string // WordPress.com site ID or domain (e.g., 12345678 or mysite.wordpress.com)
|
||||
accessToken: string // OAuth access token (injected by OAuth system)
|
||||
}
|
||||
|
||||
// WordPress.com API base URL
|
||||
export const WORDPRESS_COM_API_BASE = 'https://public-api.wordpress.com/wp/v2/sites'
|
||||
|
||||
// Post status types
|
||||
export type PostStatus = 'publish' | 'draft' | 'pending' | 'private' | 'future'
|
||||
|
||||
// Comment status types
|
||||
export type CommentStatus = 'approved' | 'hold' | 'spam' | 'trash'
|
||||
|
||||
// ============================================
|
||||
// POST OPERATIONS
|
||||
// ============================================
|
||||
|
||||
// Create Post
|
||||
export interface WordPressCreatePostParams extends WordPressBaseParams {
|
||||
title: string
|
||||
content?: string
|
||||
status?: PostStatus
|
||||
excerpt?: string
|
||||
categories?: string // Comma-separated category IDs
|
||||
tags?: string // Comma-separated tag IDs
|
||||
featuredMedia?: number
|
||||
slug?: string
|
||||
}
|
||||
|
||||
interface WordPressPost {
|
||||
id: number
|
||||
date: string
|
||||
modified: string
|
||||
slug: string
|
||||
status: PostStatus
|
||||
type: string
|
||||
link: string
|
||||
title: {
|
||||
rendered: string
|
||||
}
|
||||
content: {
|
||||
rendered: string
|
||||
}
|
||||
excerpt: {
|
||||
rendered: string
|
||||
}
|
||||
author: number
|
||||
featured_media: number
|
||||
categories: number[]
|
||||
tags: number[]
|
||||
}
|
||||
|
||||
export interface WordPressCreatePostResponse extends ToolResponse {
|
||||
output: {
|
||||
post: WordPressPost
|
||||
}
|
||||
}
|
||||
|
||||
// Update Post
|
||||
export interface WordPressUpdatePostParams extends WordPressBaseParams {
|
||||
postId: number
|
||||
title?: string
|
||||
content?: string
|
||||
status?: PostStatus
|
||||
excerpt?: string
|
||||
categories?: string
|
||||
tags?: string
|
||||
featuredMedia?: number
|
||||
slug?: string
|
||||
}
|
||||
|
||||
export interface WordPressUpdatePostResponse extends ToolResponse {
|
||||
output: {
|
||||
post: WordPressPost
|
||||
}
|
||||
}
|
||||
|
||||
// Delete Post
|
||||
export interface WordPressDeletePostParams extends WordPressBaseParams {
|
||||
postId: number
|
||||
force?: boolean // Bypass trash and force delete
|
||||
}
|
||||
|
||||
export interface WordPressDeletePostResponse extends ToolResponse {
|
||||
output: {
|
||||
deleted: boolean
|
||||
post: WordPressPost
|
||||
}
|
||||
}
|
||||
|
||||
// Get Post
|
||||
export interface WordPressGetPostParams extends WordPressBaseParams {
|
||||
postId: number
|
||||
}
|
||||
|
||||
export interface WordPressGetPostResponse extends ToolResponse {
|
||||
output: {
|
||||
post: WordPressPost
|
||||
}
|
||||
}
|
||||
|
||||
// List Posts
|
||||
export interface WordPressListPostsParams extends WordPressBaseParams {
|
||||
perPage?: number
|
||||
page?: number
|
||||
status?: PostStatus
|
||||
author?: number
|
||||
categories?: string
|
||||
tags?: string
|
||||
search?: string
|
||||
orderBy?: 'date' | 'id' | 'title' | 'slug' | 'modified'
|
||||
order?: 'asc' | 'desc'
|
||||
}
|
||||
|
||||
export interface WordPressListPostsResponse extends ToolResponse {
|
||||
output: {
|
||||
posts: WordPressPost[]
|
||||
total: number
|
||||
totalPages: number
|
||||
}
|
||||
}
|
||||
|
||||
// Search Posts
|
||||
interface WordPressSearchPostsParams extends WordPressBaseParams {
|
||||
query: string
|
||||
perPage?: number
|
||||
page?: number
|
||||
}
|
||||
|
||||
interface WordPressSearchPostsResponse extends ToolResponse {
|
||||
output: {
|
||||
posts: WordPressPost[]
|
||||
total: number
|
||||
totalPages: number
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// PAGE OPERATIONS
|
||||
// ============================================
|
||||
|
||||
// Create Page
|
||||
export interface WordPressCreatePageParams extends WordPressBaseParams {
|
||||
title: string
|
||||
content?: string
|
||||
status?: PostStatus
|
||||
excerpt?: string
|
||||
parent?: number
|
||||
menuOrder?: number
|
||||
featuredMedia?: number
|
||||
slug?: string
|
||||
}
|
||||
|
||||
interface WordPressPage {
|
||||
id: number
|
||||
date: string
|
||||
modified: string
|
||||
slug: string
|
||||
status: PostStatus
|
||||
type: string
|
||||
link: string
|
||||
title: {
|
||||
rendered: string
|
||||
}
|
||||
content: {
|
||||
rendered: string
|
||||
}
|
||||
excerpt: {
|
||||
rendered: string
|
||||
}
|
||||
author: number
|
||||
featured_media: number
|
||||
parent: number
|
||||
menu_order: number
|
||||
}
|
||||
|
||||
export interface WordPressCreatePageResponse extends ToolResponse {
|
||||
output: {
|
||||
page: WordPressPage
|
||||
}
|
||||
}
|
||||
|
||||
// Update Page
|
||||
export interface WordPressUpdatePageParams extends WordPressBaseParams {
|
||||
pageId: number
|
||||
title?: string
|
||||
content?: string
|
||||
status?: PostStatus
|
||||
excerpt?: string
|
||||
parent?: number
|
||||
menuOrder?: number
|
||||
featuredMedia?: number
|
||||
slug?: string
|
||||
}
|
||||
|
||||
export interface WordPressUpdatePageResponse extends ToolResponse {
|
||||
output: {
|
||||
page: WordPressPage
|
||||
}
|
||||
}
|
||||
|
||||
// Delete Page
|
||||
export interface WordPressDeletePageParams extends WordPressBaseParams {
|
||||
pageId: number
|
||||
force?: boolean
|
||||
}
|
||||
|
||||
export interface WordPressDeletePageResponse extends ToolResponse {
|
||||
output: {
|
||||
deleted: boolean
|
||||
page: WordPressPage
|
||||
}
|
||||
}
|
||||
|
||||
// Get Page
|
||||
export interface WordPressGetPageParams extends WordPressBaseParams {
|
||||
pageId: number
|
||||
}
|
||||
|
||||
export interface WordPressGetPageResponse extends ToolResponse {
|
||||
output: {
|
||||
page: WordPressPage
|
||||
}
|
||||
}
|
||||
|
||||
// List Pages
|
||||
export interface WordPressListPagesParams extends WordPressBaseParams {
|
||||
perPage?: number
|
||||
page?: number
|
||||
status?: PostStatus
|
||||
parent?: number
|
||||
search?: string
|
||||
orderBy?: 'date' | 'id' | 'title' | 'slug' | 'modified' | 'menu_order'
|
||||
order?: 'asc' | 'desc'
|
||||
}
|
||||
|
||||
export interface WordPressListPagesResponse extends ToolResponse {
|
||||
output: {
|
||||
pages: WordPressPage[]
|
||||
total: number
|
||||
totalPages: number
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// MEDIA OPERATIONS
|
||||
// ============================================
|
||||
|
||||
// Upload Media
|
||||
export interface WordPressUploadMediaParams extends WordPressBaseParams {
|
||||
file: UserFile
|
||||
filename?: string // Optional filename override
|
||||
title?: string
|
||||
caption?: string
|
||||
altText?: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
interface WordPressMedia {
|
||||
id: number
|
||||
date: string
|
||||
slug: string
|
||||
type: string
|
||||
link: string
|
||||
title: {
|
||||
rendered: string
|
||||
}
|
||||
caption: {
|
||||
rendered: string
|
||||
}
|
||||
alt_text: string
|
||||
media_type: string
|
||||
mime_type: string
|
||||
source_url: string
|
||||
media_details?: {
|
||||
width?: number
|
||||
height?: number
|
||||
file?: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface WordPressUploadMediaResponse extends ToolResponse {
|
||||
output: {
|
||||
media: WordPressMedia
|
||||
}
|
||||
}
|
||||
|
||||
// Get Media
|
||||
export interface WordPressGetMediaParams extends WordPressBaseParams {
|
||||
mediaId: number
|
||||
}
|
||||
|
||||
export interface WordPressGetMediaResponse extends ToolResponse {
|
||||
output: {
|
||||
media: WordPressMedia
|
||||
}
|
||||
}
|
||||
|
||||
// List Media
|
||||
export interface WordPressListMediaParams extends WordPressBaseParams {
|
||||
perPage?: number
|
||||
page?: number
|
||||
search?: string
|
||||
mediaType?: 'image' | 'video' | 'audio' | 'application'
|
||||
mimeType?: string
|
||||
orderBy?: 'date' | 'id' | 'title' | 'slug'
|
||||
order?: 'asc' | 'desc'
|
||||
}
|
||||
|
||||
export interface WordPressListMediaResponse extends ToolResponse {
|
||||
output: {
|
||||
media: WordPressMedia[]
|
||||
total: number
|
||||
totalPages: number
|
||||
}
|
||||
}
|
||||
|
||||
// Delete Media
|
||||
export interface WordPressDeleteMediaParams extends WordPressBaseParams {
|
||||
mediaId: number
|
||||
}
|
||||
|
||||
export interface WordPressDeleteMediaResponse extends ToolResponse {
|
||||
output: {
|
||||
deleted: boolean
|
||||
media: WordPressMedia
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// COMMENT OPERATIONS
|
||||
// ============================================
|
||||
|
||||
// Create Comment
|
||||
export interface WordPressCreateCommentParams extends WordPressBaseParams {
|
||||
postId: number
|
||||
content: string
|
||||
parent?: number
|
||||
authorName?: string
|
||||
authorEmail?: string
|
||||
authorUrl?: string
|
||||
}
|
||||
|
||||
interface WordPressComment {
|
||||
id: number
|
||||
post: number
|
||||
parent: number
|
||||
author: number
|
||||
author_name: string
|
||||
author_email?: string
|
||||
author_url: string
|
||||
date: string
|
||||
content: {
|
||||
rendered: string
|
||||
}
|
||||
link: string
|
||||
status: string
|
||||
}
|
||||
|
||||
export interface WordPressCreateCommentResponse extends ToolResponse {
|
||||
output: {
|
||||
comment: WordPressComment
|
||||
}
|
||||
}
|
||||
|
||||
// Get Comment
|
||||
interface WordPressGetCommentParams extends WordPressBaseParams {
|
||||
commentId: number
|
||||
}
|
||||
|
||||
interface WordPressGetCommentResponse extends ToolResponse {
|
||||
output: {
|
||||
comment: WordPressComment
|
||||
}
|
||||
}
|
||||
|
||||
// List Comments
|
||||
export interface WordPressListCommentsParams extends WordPressBaseParams {
|
||||
perPage?: number
|
||||
page?: number
|
||||
postId?: number
|
||||
status?: CommentStatus
|
||||
search?: string
|
||||
orderBy?: 'date' | 'id' | 'parent'
|
||||
order?: 'asc' | 'desc'
|
||||
}
|
||||
|
||||
export interface WordPressListCommentsResponse extends ToolResponse {
|
||||
output: {
|
||||
comments: WordPressComment[]
|
||||
total: number
|
||||
totalPages: number
|
||||
}
|
||||
}
|
||||
|
||||
// Update Comment
|
||||
export interface WordPressUpdateCommentParams extends WordPressBaseParams {
|
||||
commentId: number
|
||||
content?: string
|
||||
status?: CommentStatus
|
||||
}
|
||||
|
||||
export interface WordPressUpdateCommentResponse extends ToolResponse {
|
||||
output: {
|
||||
comment: WordPressComment
|
||||
}
|
||||
}
|
||||
|
||||
// Delete Comment
|
||||
export interface WordPressDeleteCommentParams extends WordPressBaseParams {
|
||||
commentId: number
|
||||
force?: boolean
|
||||
}
|
||||
|
||||
export interface WordPressDeleteCommentResponse extends ToolResponse {
|
||||
output: {
|
||||
deleted: boolean
|
||||
comment: WordPressComment
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// TAXONOMY OPERATIONS (Categories & Tags)
|
||||
// ============================================
|
||||
|
||||
// Create Category
|
||||
export interface WordPressCreateCategoryParams extends WordPressBaseParams {
|
||||
name: string
|
||||
description?: string
|
||||
parent?: number
|
||||
slug?: string
|
||||
}
|
||||
|
||||
interface WordPressCategory {
|
||||
id: number
|
||||
count: number
|
||||
description: string
|
||||
link: string
|
||||
name: string
|
||||
slug: string
|
||||
taxonomy: string
|
||||
parent: number
|
||||
}
|
||||
|
||||
export interface WordPressCreateCategoryResponse extends ToolResponse {
|
||||
output: {
|
||||
category: WordPressCategory
|
||||
}
|
||||
}
|
||||
|
||||
// List Categories
|
||||
export interface WordPressListCategoriesParams extends WordPressBaseParams {
|
||||
perPage?: number
|
||||
page?: number
|
||||
search?: string
|
||||
order?: 'asc' | 'desc'
|
||||
}
|
||||
|
||||
export interface WordPressListCategoriesResponse extends ToolResponse {
|
||||
output: {
|
||||
categories: WordPressCategory[]
|
||||
total: number
|
||||
totalPages: number
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
description?: string
|
||||
slug?: string
|
||||
}
|
||||
|
||||
interface WordPressTag {
|
||||
id: number
|
||||
count: number
|
||||
description: string
|
||||
link: string
|
||||
name: string
|
||||
slug: string
|
||||
taxonomy: string
|
||||
}
|
||||
|
||||
export interface WordPressCreateTagResponse extends ToolResponse {
|
||||
output: {
|
||||
tag: WordPressTag
|
||||
}
|
||||
}
|
||||
|
||||
// List Tags
|
||||
export interface WordPressListTagsParams extends WordPressBaseParams {
|
||||
perPage?: number
|
||||
page?: number
|
||||
search?: string
|
||||
order?: 'asc' | 'desc'
|
||||
}
|
||||
|
||||
export interface WordPressListTagsResponse extends ToolResponse {
|
||||
output: {
|
||||
tags: WordPressTag[]
|
||||
total: number
|
||||
totalPages: number
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
// ============================================
|
||||
|
||||
// Get Current User
|
||||
export interface WordPressGetCurrentUserParams extends WordPressBaseParams {}
|
||||
|
||||
interface WordPressUser {
|
||||
id: number
|
||||
username: string
|
||||
name: string
|
||||
first_name: string
|
||||
last_name: string
|
||||
email?: string
|
||||
url: string
|
||||
description: string
|
||||
link: string
|
||||
slug: string
|
||||
roles: string[]
|
||||
avatar_urls?: Record<string, string>
|
||||
}
|
||||
|
||||
export interface WordPressGetCurrentUserResponse extends ToolResponse {
|
||||
output: {
|
||||
user: WordPressUser
|
||||
}
|
||||
}
|
||||
|
||||
// List Users
|
||||
export interface WordPressListUsersParams extends WordPressBaseParams {
|
||||
perPage?: number
|
||||
page?: number
|
||||
search?: string
|
||||
roles?: string
|
||||
order?: 'asc' | 'desc'
|
||||
}
|
||||
|
||||
export interface WordPressListUsersResponse extends ToolResponse {
|
||||
output: {
|
||||
users: WordPressUser[]
|
||||
total: number
|
||||
totalPages: number
|
||||
}
|
||||
}
|
||||
|
||||
// Get User
|
||||
export interface WordPressGetUserParams extends WordPressBaseParams {
|
||||
userId: number
|
||||
}
|
||||
|
||||
export interface WordPressGetUserResponse extends ToolResponse {
|
||||
output: {
|
||||
user: WordPressUser
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// SEARCH OPERATIONS
|
||||
// ============================================
|
||||
|
||||
// Search Content
|
||||
export interface WordPressSearchContentParams extends WordPressBaseParams {
|
||||
query: string
|
||||
perPage?: number
|
||||
page?: number
|
||||
type?: 'post' | 'term' | 'post-format'
|
||||
subtype?: string
|
||||
}
|
||||
|
||||
interface WordPressSearchResult {
|
||||
id: number
|
||||
title: string
|
||||
url: string
|
||||
type: string
|
||||
subtype: string
|
||||
}
|
||||
|
||||
export interface WordPressSearchContentResponse extends ToolResponse {
|
||||
output: {
|
||||
results: WordPressSearchResult[]
|
||||
total: number
|
||||
totalPages: number
|
||||
}
|
||||
}
|
||||
|
||||
// Union type for all WordPress responses
|
||||
export type WordPressResponse =
|
||||
| WordPressCreatePostResponse
|
||||
| WordPressUpdatePostResponse
|
||||
| WordPressDeletePostResponse
|
||||
| WordPressGetPostResponse
|
||||
| WordPressListPostsResponse
|
||||
| WordPressSearchPostsResponse
|
||||
| WordPressCreatePageResponse
|
||||
| WordPressUpdatePageResponse
|
||||
| WordPressDeletePageResponse
|
||||
| WordPressGetPageResponse
|
||||
| WordPressListPagesResponse
|
||||
| WordPressUploadMediaResponse
|
||||
| WordPressGetMediaResponse
|
||||
| WordPressListMediaResponse
|
||||
| WordPressDeleteMediaResponse
|
||||
| WordPressCreateCommentResponse
|
||||
| WordPressGetCommentResponse
|
||||
| WordPressListCommentsResponse
|
||||
| WordPressUpdateCommentResponse
|
||||
| WordPressDeleteCommentResponse
|
||||
| WordPressCreateCategoryResponse
|
||||
| WordPressListCategoriesResponse
|
||||
| WordPressGetCategoryResponse
|
||||
| WordPressUpdateCategoryResponse
|
||||
| WordPressDeleteCategoryResponse
|
||||
| WordPressCreateTagResponse
|
||||
| WordPressListTagsResponse
|
||||
| WordPressGetTagResponse
|
||||
| WordPressUpdateTagResponse
|
||||
| WordPressDeleteTagResponse
|
||||
| WordPressGetCurrentUserResponse
|
||||
| WordPressListUsersResponse
|
||||
| WordPressGetUserResponse
|
||||
| WordPressSearchContentResponse
|
||||
@@ -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<string, any> = {}
|
||||
|
||||
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' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressUpdateCommentParams,
|
||||
type WordPressUpdateCommentResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const updateCommentTool: ToolConfig<
|
||||
WordPressUpdateCommentParams,
|
||||
WordPressUpdateCommentResponse
|
||||
> = {
|
||||
id: 'wordpress_update_comment',
|
||||
name: 'WordPress Update Comment',
|
||||
description: 'Update a comment in WordPress.com (content or status)',
|
||||
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)',
|
||||
},
|
||||
commentId: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the comment to update',
|
||||
},
|
||||
content: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Updated comment content',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comment status: approved, hold, spam, trash',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `${WORDPRESS_COM_API_BASE}/${params.siteId}/comments/${params.commentId}`,
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {}
|
||||
|
||||
if (params.content) body.content = params.content
|
||||
if (params.status) body.status = params.status
|
||||
|
||||
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: {
|
||||
comment: {
|
||||
id: data.id,
|
||||
post: data.post,
|
||||
parent: data.parent,
|
||||
author: data.author,
|
||||
author_name: data.author_name,
|
||||
author_email: data.author_email,
|
||||
author_url: data.author_url,
|
||||
date: data.date,
|
||||
content: data.content,
|
||||
link: data.link,
|
||||
status: data.status,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
comment: {
|
||||
type: 'object',
|
||||
description: 'The updated comment',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'Comment ID' },
|
||||
post: { type: 'number', description: 'Post ID' },
|
||||
parent: { type: 'number', description: 'Parent comment ID' },
|
||||
author: { type: 'number', description: 'Author user ID' },
|
||||
author_name: { type: 'string', description: 'Author display name' },
|
||||
author_email: { type: 'string', description: 'Author email' },
|
||||
author_url: { type: 'string', description: 'Author URL' },
|
||||
date: { type: 'string', description: 'Comment date' },
|
||||
content: { type: 'object', description: 'Comment content object' },
|
||||
link: { type: 'string', description: 'Comment permalink' },
|
||||
status: { type: 'string', description: 'Comment status' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressUpdatePageParams,
|
||||
type WordPressUpdatePageResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const updatePageTool: ToolConfig<WordPressUpdatePageParams, WordPressUpdatePageResponse> = {
|
||||
id: 'wordpress_update_page',
|
||||
name: 'WordPress Update Page',
|
||||
description: 'Update an existing page 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)',
|
||||
},
|
||||
pageId: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the page to update',
|
||||
},
|
||||
title: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page title',
|
||||
},
|
||||
content: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page content (HTML or plain text)',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page status: publish, draft, pending, private',
|
||||
},
|
||||
excerpt: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page excerpt',
|
||||
},
|
||||
parent: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Parent page ID for hierarchical pages',
|
||||
},
|
||||
menuOrder: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Order in page menu',
|
||||
},
|
||||
featuredMedia: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Featured image media ID',
|
||||
},
|
||||
slug: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'URL slug for the page',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `${WORDPRESS_COM_API_BASE}/${params.siteId}/pages/${params.pageId}`,
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {}
|
||||
|
||||
if (params.title) body.title = params.title
|
||||
if (params.content) body.content = params.content
|
||||
if (params.status) body.status = params.status
|
||||
if (params.excerpt) body.excerpt = params.excerpt
|
||||
if (params.slug) body.slug = params.slug
|
||||
if (params.parent !== undefined) body.parent = params.parent
|
||||
if (params.menuOrder !== undefined) body.menu_order = params.menuOrder
|
||||
if (params.featuredMedia !== undefined) body.featured_media = params.featuredMedia
|
||||
|
||||
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: {
|
||||
page: {
|
||||
id: data.id,
|
||||
date: data.date,
|
||||
modified: data.modified,
|
||||
slug: data.slug,
|
||||
status: data.status,
|
||||
type: data.type,
|
||||
link: data.link,
|
||||
title: data.title,
|
||||
content: data.content,
|
||||
excerpt: data.excerpt,
|
||||
author: data.author,
|
||||
featured_media: data.featured_media,
|
||||
parent: data.parent,
|
||||
menu_order: data.menu_order,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
page: {
|
||||
type: 'object',
|
||||
description: 'The updated page',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'Page ID' },
|
||||
date: { type: 'string', description: 'Page creation date' },
|
||||
modified: { type: 'string', description: 'Page modification date' },
|
||||
slug: { type: 'string', description: 'Page slug' },
|
||||
status: { type: 'string', description: 'Page status' },
|
||||
type: { type: 'string', description: 'Content type' },
|
||||
link: { type: 'string', description: 'Page URL' },
|
||||
title: { type: 'object', description: 'Page title object' },
|
||||
content: { type: 'object', description: 'Page content object' },
|
||||
excerpt: { type: 'object', description: 'Page excerpt object' },
|
||||
author: { type: 'number', description: 'Author ID' },
|
||||
featured_media: { type: 'number', description: 'Featured media ID' },
|
||||
parent: { type: 'number', description: 'Parent page ID' },
|
||||
menu_order: { type: 'number', description: 'Menu order' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressUpdatePostParams,
|
||||
type WordPressUpdatePostResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const updatePostTool: ToolConfig<WordPressUpdatePostParams, WordPressUpdatePostResponse> = {
|
||||
id: 'wordpress_update_post',
|
||||
name: 'WordPress Update Post',
|
||||
description: 'Update an existing blog post 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)',
|
||||
},
|
||||
postId: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The ID of the post to update',
|
||||
},
|
||||
title: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Post title',
|
||||
},
|
||||
content: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Post content (HTML or plain text)',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Post status: publish, draft, pending, private, or future',
|
||||
},
|
||||
excerpt: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Post excerpt',
|
||||
},
|
||||
categories: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated category IDs',
|
||||
},
|
||||
tags: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Comma-separated tag IDs',
|
||||
},
|
||||
featuredMedia: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Featured image media ID',
|
||||
},
|
||||
slug: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'URL slug for the post',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => `${WORDPRESS_COM_API_BASE}/${params.siteId}/posts/${params.postId}`,
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, any> = {}
|
||||
|
||||
if (params.title) body.title = params.title
|
||||
if (params.content) body.content = params.content
|
||||
if (params.status) body.status = params.status
|
||||
if (params.excerpt) body.excerpt = params.excerpt
|
||||
if (params.slug) body.slug = params.slug
|
||||
if (params.featuredMedia !== undefined) body.featured_media = params.featuredMedia
|
||||
|
||||
if (params.categories) {
|
||||
body.categories = params.categories
|
||||
.split(',')
|
||||
.map((id: string) => Number.parseInt(id.trim(), 10))
|
||||
.filter((id: number) => !Number.isNaN(id))
|
||||
}
|
||||
|
||||
if (params.tags) {
|
||||
body.tags = params.tags
|
||||
.split(',')
|
||||
.map((id: string) => Number.parseInt(id.trim(), 10))
|
||||
.filter((id: number) => !Number.isNaN(id))
|
||||
}
|
||||
|
||||
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: {
|
||||
post: {
|
||||
id: data.id,
|
||||
date: data.date,
|
||||
modified: data.modified,
|
||||
slug: data.slug,
|
||||
status: data.status,
|
||||
type: data.type,
|
||||
link: data.link,
|
||||
title: data.title,
|
||||
content: data.content,
|
||||
excerpt: data.excerpt,
|
||||
author: data.author,
|
||||
featured_media: data.featured_media,
|
||||
categories: data.categories || [],
|
||||
tags: data.tags || [],
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
post: {
|
||||
type: 'object',
|
||||
description: 'The updated post',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'Post ID' },
|
||||
date: { type: 'string', description: 'Post creation date' },
|
||||
modified: { type: 'string', description: 'Post modification date' },
|
||||
slug: { type: 'string', description: 'Post slug' },
|
||||
status: { type: 'string', description: 'Post status' },
|
||||
type: { type: 'string', description: 'Post type' },
|
||||
link: { type: 'string', description: 'Post URL' },
|
||||
title: { type: 'object', description: 'Post title object' },
|
||||
content: { type: 'object', description: 'Post content object' },
|
||||
excerpt: { type: 'object', description: 'Post excerpt object' },
|
||||
author: { type: 'number', description: 'Author ID' },
|
||||
featured_media: { type: 'number', description: 'Featured media ID' },
|
||||
categories: { type: 'array', description: 'Category IDs' },
|
||||
tags: { type: 'array', description: 'Tag IDs' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import {
|
||||
WORDPRESS_COM_API_BASE,
|
||||
type WordPressUpdateTagParams,
|
||||
type WordPressUpdateTagResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const updateTagTool: ToolConfig<WordPressUpdateTagParams, WordPressUpdateTagResponse> = {
|
||||
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<string, any> = {}
|
||||
|
||||
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' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
import type {
|
||||
WordPressUploadMediaParams,
|
||||
WordPressUploadMediaResponse,
|
||||
} from '@/tools/wordpress/types'
|
||||
|
||||
export const uploadMediaTool: ToolConfig<WordPressUploadMediaParams, WordPressUploadMediaResponse> =
|
||||
{
|
||||
id: 'wordpress_upload_media',
|
||||
name: 'WordPress Upload Media',
|
||||
description: 'Upload a media file (image, video, document) to 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)',
|
||||
},
|
||||
file: {
|
||||
type: 'file',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'File to upload (UserFile object)',
|
||||
},
|
||||
filename: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Optional filename override (e.g., image.jpg)',
|
||||
},
|
||||
title: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Media title',
|
||||
},
|
||||
caption: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Media caption',
|
||||
},
|
||||
altText: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Alternative text for accessibility',
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Media description',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => '/api/tools/wordpress/upload',
|
||||
method: 'POST',
|
||||
headers: () => ({
|
||||
'Content-Type': 'application/json',
|
||||
}),
|
||||
body: (params) => ({
|
||||
accessToken: params.accessToken,
|
||||
siteId: params.siteId,
|
||||
file: params.file,
|
||||
filename: params.filename,
|
||||
title: params.title,
|
||||
caption: params.caption,
|
||||
altText: params.altText,
|
||||
description: params.description,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response) => {
|
||||
const data = await response.json()
|
||||
|
||||
if (!data.success) {
|
||||
throw new Error(data.error || 'Failed to upload media to WordPress')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
media: data.output.media,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
media: {
|
||||
type: 'object',
|
||||
description: 'The uploaded media item',
|
||||
properties: {
|
||||
id: { type: 'number', description: 'Media ID' },
|
||||
date: { type: 'string', description: 'Upload date' },
|
||||
slug: { type: 'string', description: 'Media slug' },
|
||||
type: { type: 'string', description: 'Content type' },
|
||||
link: { type: 'string', description: 'Media page URL' },
|
||||
title: { type: 'object', description: 'Media title object' },
|
||||
caption: { type: 'object', description: 'Media caption object' },
|
||||
alt_text: { type: 'string', description: 'Alt text' },
|
||||
media_type: { type: 'string', description: 'Media type (image, video, etc.)' },
|
||||
mime_type: { type: 'string', description: 'MIME type' },
|
||||
source_url: { type: 'string', description: 'Direct URL to the media file' },
|
||||
media_details: { type: 'object', description: 'Media details (dimensions, etc.)' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user