feishu_fabu/wp-tools/index_extensions.js
shaowu 860e8aaa46 fix: wp-tools 插件修复 - register 同步化 + images 参数 + 新增 wp_publish_with_image 工具
修复内容:
- 修复 register must be synchronous 错误(去掉 async 关键字)
- wp_publish 新增 images 参数支持图片上传到 WordPress 媒体库
- 新增 wp_publish_with_image 工具一步完成生图 + 发布
- 更新 wp_generate_image 描述说明图片上传流程

修改文件:
- wp-tools/index.js (data/plugins/wp-tools/index.js)
- wp-tools/index_extensions.js (data/extensions/wp-tools/index.js)
- wp-tools/openclaw.plugin.json (更新 contracts.tools 列表)
2026-05-14 15:00:20 +08:00

324 lines
9.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* WordPress Tools - OpenClaw 插件
* 提供 WordPress 发布和 AI 生图工具
*
* 修复说明:
* 1. register 改为同步方法(解决 "register must be synchronous" 错误)
* 2. wp_publish 新增 images 参数(支持传入图片路径上传到媒体库)
* 3. 新增 wp_publish_with_image 工具(一步完成生图+发布)
*/
import { spawn } from 'child_process';
// WordPress 发布脚本路径
const WP_PUBLISH_SCRIPT = '/www/wwwroot/wp-publish/scripts/wp_publish_text.py';
const WP_GENERATE_SCRIPT = '/www/wwwroot/wp-publish/scripts/wp_generate_image.py';
const PYTHON_PATH = '/usr/bin/python3';
/**
* 执行 Python 脚本
*/
function executePythonScript(scriptPath, args) {
return new Promise((resolve, reject) => {
const process = spawn(PYTHON_PATH, [scriptPath, ...args], {
env: { ...process.env },
stdio: ['pipe', 'pipe', 'pipe']
});
let stdout = '';
let stderr = '';
process.stdout.on('data', (data) => {
stdout += data.toString();
});
process.stderr.on('data', (data) => {
stderr += data.toString();
});
process.on('close', (code) => {
if (code === 0) {
resolve(stdout);
} else {
reject(new Error(`脚本执行失败: ${stderr}`));
}
});
process.on('error', (error) => {
reject(error);
});
});
}
/**
* 定义插件入口
*/
export default {
id: 'wp-tools',
name: 'WordPress Tools',
description: 'WordPress 发布和 AI 生图工具',
// 修复1去掉 async改为同步注册
register(api) {
// ========== 工具 1WordPress 发布 ==========
api.registerTool({
name: 'wp_publish',
description: '发布文章到 WordPress 网站。支持文字内容和图片上传。',
parameters: {
type: 'object',
properties: {
text: {
type: 'string',
description: '文章内容(必填)'
},
title: {
type: 'string',
description: '文章标题(可选,默认从内容提取)'
},
category: {
type: 'string',
description: '分类名称ai, ai-kepu, jishu 等)'
},
tags: {
type: 'string',
description: '标签(可选)'
},
status: {
type: 'string',
description: '发布状态publish/draft',
enum: ['publish', 'draft']
},
images: {
type: 'string',
description: '图片文件路径可选多个路径用逗号分隔。AI 生图完成后,将返回的图片路径传入此参数即可自动上传到 WordPress 媒体库。'
}
},
required: ['text']
},
async execute(_id, params) {
try {
const args = [
params.text,
'--title', params.title || '',
'--instruction', params.category ? `#分类 ${params.category}` : '',
'--status', params.status || 'publish'
];
// 修复2支持传入图片路径
if (params.images) {
const imagePaths = params.images.split(',').map(p => p.trim()).filter(Boolean);
for (const imgPath of imagePaths) {
args.push('--images', imgPath);
}
}
const result = await executePythonScript(WP_PUBLISH_SCRIPT, args);
return {
content: [{
type: 'text',
text: `✅ 文章发布成功!\n\n${result}`
}]
};
} catch (error) {
return {
content: [{
type: 'text',
text: `❌ 发布失败:${error.message}`
}]
};
}
}
});
// ========== 工具 2AI 生图 ==========
api.registerTool({
name: 'wp_generate_image',
description: '使用 AI 生成图片。支持通义万相模型,可指定尺寸、格式和数量。生成后的图片可通过 wp_publish 的 images 参数上传到 WordPress 媒体库。',
parameters: {
type: 'object',
properties: {
prompt: {
type: 'string',
description: '图片描述(必填,如:一只可爱的猫咪在草地上晒太阳)'
},
model: {
type: 'string',
description: '模型名称默认wanx-v1',
enum: ['wanx-v1', 'wanx2.1-t2i-turbo', 'wanx2.1-t2i-plus']
},
size: {
type: 'string',
description: '图片尺寸默认1024*1024',
enum: ['1024*1024', '720*1280', '1280*720', '512*512']
},
format: {
type: 'string',
description: '图片格式默认webp',
enum: ['webp', 'jpg', 'png']
},
count: {
type: 'number',
description: '生成数量1-4默认1',
minimum: 1,
maximum: 4
},
style: {
type: 'string',
description: '图片风格(如:写实、动漫、水彩等)'
}
},
required: ['prompt']
},
async execute(_id, params) {
try {
const args = [
params.prompt,
'--model', params.model || 'wanx-v1',
'--size', params.size || '1024*1024',
'--format', params.format || 'webp',
'--count', params.count || 1
];
if (params.style) {
args.push('--style', params.style);
}
const result = await executePythonScript(WP_GENERATE_SCRIPT, args);
return {
content: [{
type: 'text',
text: `✅ AI 生图完成!\n\n${result}`
}]
};
} catch (error) {
return {
content: [{
type: 'text',
text: `❌ AI 生图失败:${error.message}`
}]
};
}
}
});
// ========== 工具 3生图并发布新增 ==========
api.registerTool({
name: 'wp_publish_with_image',
description: '一步完成 AI 生图并发布到 WordPress。自动执行生图 → 上传到媒体库 → 发布文章。',
parameters: {
type: 'object',
properties: {
title: {
type: 'string',
description: '文章标题(必填)'
},
text: {
type: 'string',
description: '文章内容(必填)'
},
image_prompt: {
type: 'string',
description: '图片描述(必填,用于 AI 生图)'
},
image_model: {
type: 'string',
description: '生图模型默认wanx-v1',
enum: ['wanx-v1', 'wanx2.1-t2i-turbo', 'wanx2.1-t2i-plus']
},
image_size: {
type: 'string',
description: '图片尺寸默认1024*1024',
enum: ['1024*1024', '720*1280', '1280*720', '512*512']
},
category: {
type: 'string',
description: '分类名称'
},
tags: {
type: 'string',
description: '标签'
},
status: {
type: 'string',
description: '发布状态publish/draft',
enum: ['publish', 'draft']
}
},
required: ['title', 'text', 'image_prompt']
},
async execute(_id, params) {
try {
// 步骤1先调用生图
const genArgs = [
params.image_prompt,
'--model', params.image_model || 'wanx-v1',
'--size', params.image_size || '1024*1024',
'--format', 'jpg',
'--count', '1'
];
const genResult = await executePythonScript(WP_GENERATE_SCRIPT, genArgs);
// 从生图结果中提取图片路径
let imagePath = '';
try {
// 尝试从输出中提取 JSON 中的 paths
const jsonMatch = genResult.match(/\{[\s\S]*"paths"[\s\S]*\}/);
if (jsonMatch) {
const genJson = JSON.parse(jsonMatch[0]);
if (genJson.paths && genJson.paths.length > 0) {
imagePath = genJson.paths[0];
}
}
} catch (e) {
// 如果解析失败,尝试从文本中提取路径
const pathMatch = genResult.match(/\/www\/wwwroot\/wp-publish\/temp\/[\w.]+/);
if (pathMatch) {
imagePath = pathMatch[0];
}
}
if (!imagePath) {
return {
content: [{
type: 'text',
text: `⚠️ 图片生成完成但未找到路径,直接发布文字内容。\n\n生图结果:${genResult}`
}]
};
}
// 步骤2发布文章并上传图片
const pubArgs = [
params.text,
'--title', params.title,
'--instruction', params.category ? `#分类 ${params.category}` : '',
'--status', params.status || 'publish',
'--images', imagePath
];
const pubResult = await executePythonScript(WP_PUBLISH_SCRIPT, pubArgs);
return {
content: [{
type: 'text',
text: `✅ 生图并发布成功!\n\n生图结果:${genResult}\n\n发布结果:${pubResult}`
}]
};
} catch (error) {
return {
content: [{
type: 'text',
text: `❌ 操作失败:${error.message}`
}]
};
}
}
});
console.log('[wp-tools] WordPress 工具已注册');
}
};