test-skill-flow.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /**
  2. * OpenClaw Skill 完整流程测试
  3. * 模拟 OpenClaw 读取 api-config.json → 构造请求 → 提交任务 → 轮询结果
  4. */
  5. const fs = require('fs');
  6. const path = require('path');
  7. const TOKEN = "Bearer r:f0333969e312a40e4703e8fe4ed1c600";
  8. // ========== Step 0: 读取 skill 配置 ==========
  9. function loadSkillConfig(skillDir) {
  10. const configPath = path.join(__dirname, skillDir, 'api-config.json');
  11. const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
  12. console.log(`[OpenClaw] 加载 skill: ${config.displayName} (${config.name})`);
  13. console.log(`[OpenClaw] 端点: ${config.endpoint.method} ${config.endpoint.url}`);
  14. console.log(`[OpenClaw] 必填参数: ${config.parameters.required.join(', ')}`);
  15. return config;
  16. }
  17. // ========== Step 1: 根据 api-config 构造并发送请求 ==========
  18. async function executeSkill(config, inputParams) {
  19. console.log(`\n[OpenClaw] 执行 skill: ${config.name}`);
  20. console.log(`[OpenClaw] 输入参数:`, JSON.stringify(inputParams, null, 2));
  21. // 验证必填参数
  22. for (const req of config.parameters.required) {
  23. if (!(req in inputParams)) {
  24. throw new Error(`缺少必填参数: ${req}`);
  25. }
  26. }
  27. // 构造请求
  28. const response = await fetch(config.endpoint.url, {
  29. method: config.endpoint.method,
  30. headers: config.endpoint.headers,
  31. body: JSON.stringify(inputParams)
  32. });
  33. const result = await response.json();
  34. console.log(`[OpenClaw] 响应:`, JSON.stringify(result, null, 2));
  35. return result;
  36. }
  37. // ========== Step 2: 轮询任务状态 ==========
  38. async function pollTaskResult(taskQueryConfig, workId, routerName, maxAttempts = 20, intervalMs = 3000) {
  39. console.log(`\n[OpenClaw] 开始轮询任务 workId=${workId}, routerName=${routerName}`);
  40. for (let i = 1; i <= maxAttempts; i++) {
  41. const result = await executeSkill(taskQueryConfig, {
  42. workId: workId,
  43. routerName: routerName,
  44. token: TOKEN
  45. });
  46. if (result.code === 200 && result.data) {
  47. console.log(`[OpenClaw] 轮询 #${i}: tip="${result.data.tip}", isFinish=${result.data.isFinish}`);
  48. if (result.data.isFinish === true) {
  49. console.log(`[OpenClaw] ✅ 任务完成!`);
  50. return result;
  51. }
  52. }
  53. if (i < maxAttempts) {
  54. console.log(`[OpenClaw] 等待 ${intervalMs}ms 后重试...`);
  55. await new Promise(resolve => setTimeout(resolve, intervalMs));
  56. }
  57. }
  58. console.log(`[OpenClaw] ⚠️ 轮询超时,已达最大尝试次数 ${maxAttempts}`);
  59. return null;
  60. }
  61. // ========== 主测试流程 ==========
  62. async function testImgV4Flow() {
  63. console.log("=".repeat(60));
  64. console.log("测试1: jimeng-img-v4 图片生成4.0 完整流程");
  65. console.log("=".repeat(60));
  66. // Step 0: 加载两个 skill 配置
  67. const imgConfig = loadSkillConfig('jimeng-img-v4');
  68. const queryConfig = loadSkillConfig('jimeng-task-query');
  69. // Step 1: 提交图片生成任务
  70. const genResult = await executeSkill(imgConfig, {
  71. prompt: "一只可爱的橘猫在阳光下打盹,水彩画风格",
  72. sizeDate: { width: 1024, height: 1024 },
  73. scale: 0.6,
  74. force_single: true,
  75. token: TOKEN
  76. });
  77. if (genResult.code !== 200 || !genResult.data?.workId) {
  78. console.log("[OpenClaw] ❌ 任务提交失败");
  79. return;
  80. }
  81. const workId = genResult.data.workId;
  82. console.log(`[OpenClaw] 任务已提交, workId = ${workId}`);
  83. // Step 2: 轮询任务结果
  84. const taskResult = await pollTaskResult(queryConfig, workId, 'getImgV4');
  85. if (taskResult) {
  86. console.log(`\n[OpenClaw] 🎉 jimeng-img-v4 完整流程测试通过!`);
  87. console.log(`[OpenClaw] workId: ${workId}`);
  88. console.log(`[OpenClaw] 可通过查询 ImagineWork 表 (objectId=${workId}) 获取 images 字段`);
  89. }
  90. }
  91. async function testText2ImgV3Flow() {
  92. console.log("\n" + "=".repeat(60));
  93. console.log("测试2: jimeng-text2img-v3 文生图3.0 完整流程");
  94. console.log("=".repeat(60));
  95. const imgConfig = loadSkillConfig('jimeng-text2img-v3');
  96. const queryConfig = loadSkillConfig('jimeng-task-query');
  97. const genResult = await executeSkill(imgConfig, {
  98. prompt: "春天的樱花树下,一位穿和服的少女,唯美水彩风",
  99. use_pre_llm: true,
  100. sizeDate: { width: 1328, height: 1328 },
  101. token: TOKEN
  102. });
  103. if (genResult.code !== 200 || !genResult.data?.workId) {
  104. console.log("[OpenClaw] ❌ 任务提交失败");
  105. return;
  106. }
  107. const workId = genResult.data.workId;
  108. console.log(`[OpenClaw] 任务已提交, workId = ${workId}`);
  109. const taskResult = await pollTaskResult(queryConfig, workId, 'getText2ImgV3');
  110. if (taskResult) {
  111. console.log(`\n[OpenClaw] 🎉 jimeng-text2img-v3 完整流程测试通过!`);
  112. console.log(`[OpenClaw] workId: ${workId}`);
  113. }
  114. }
  115. async function main() {
  116. console.log("╔══════════════════════════════════════════════════════════╗");
  117. console.log("║ OpenClaw Jimeng Skill 完整流程测试 ║");
  118. console.log("╚══════════════════════════════════════════════════════════╝\n");
  119. try {
  120. await testImgV4Flow();
  121. await testText2ImgV3Flow();
  122. } catch (err) {
  123. console.error("[OpenClaw] 测试出错:", err.message);
  124. }
  125. console.log("\n" + "=".repeat(60));
  126. console.log("全部测试完成");
  127. console.log("=".repeat(60));
  128. }
  129. main();