Skill: shishugen/liblibai (version 1.0.0)

--- name: liblibai description: 使用 LiblibAI API 生成 AI 图像。支持文生图、图生图、Ultra 模型、ComfyUI 工作流和文件上传，适合创意设计、内容创作和视觉项目。 license: MIT allowed-tools: - Read - Write - Exec - WebFetch - AskUserQuestion metadata: clawdbot: emoji: 🎨 requires: bins: [node, npm] install: - id: npm kind: npm pkg: liblibai label: 安装 liblibai npm 包 config: - name: LIBLIBAI_ACCESS_KEY description: LiblibAI API AccessKey（在 https://liblibai.com 账户设置中获取） required: true example: "AFP8cs3Ip4KsQJr7tmUcWA" - name: LIBLIBAI_SECRET_KEY description: LiblibAI API SecretKey（与 AccessKey 配对） required: true - name: LIBLIBAI_BASE_URL description: API 端点 URL（默认: https://openapi.liblibai.cloud） default: https://openapi.liblibai.cloud optional: true --- # LiblibAI Skill - AI 图像生成 强大的 AI 图像生成工具，基于 LiblibAI（星流）平台。适用于： - 🎨 **创意设计**：概念图、角色设计、场景插画 - 📱 **内容创作**：社媒配图、文章插图、营销素材 - 🔬 **视觉实验**：风格转换、图像重绘、ControlNet 控制 - 🛠️ **工作流集成**：与其他 OpenClaw 技能组合（如 web_search 找灵感，humanizer 优化提示词） --- ## 快速开始 ### 1. 获取 API 凭据 访问 [LiblibAI](https://liblibai.com)： 1. 注册/登录账户 2. 进入「API 管理」或「开发者设置」 3. 创建 AccessKey 和 SecretKey 4. 设置环境变量（推荐）： ```bash export LIBLIBAI_ACCESS_KEY="your-access-key" export LIBLIBAI_SECRET_KEY="your-secret-key" ``` 或通过 OpenClaw 配置系统设置。 ### 2. 基本生成 ```bash # 生成一张 1024x1024 的小狗图片 ./skills/liblibai/bin/cli.js text2img -p "一只可爱的小狗，真实照片风格，高清" -W 1024 -H 1024 -s 20 # 查看结果（成功后输出图片 URL） # 复制 URL 到浏览器即可查看 ``` --- ## 核心功能 ### 文生图 (text2img) 从文本生成图像，支持完整参数控制。 **常用参数：** ``` -p, --prompt <text> 正向提示词（必需） -n, --negative-prompt <text> 负向提示词（如 "ugly, blurry"） -W, --width <1024> 图像宽度（建议 512-1536） -H, --height <1024> 图像高度 -s, --steps <20> 采样步数（10-50，越高越精细） -c, --cfg-scale <7> 提示词引导系数（1-20） --sampler <15> 采样方法 ID（15=DPMSolver） --seed <-1> 随机种子（-1=随机） -i, --img-count <1> 生成数量（1-4） -t, --template-uuid <uuid> 参数模板 ID（在 LiblibAI 平台预设） ``` **示例：** ```bash # 生成插画风格头像 ./bin/cli.js text2img -p "anime portrait, 1girl, colorful hair, detailed eyes" -W 768 -H 1024 -s 30 -c 8 # 使用预设模板（需要先在平台创建） ./bin/cli.js text2img -p " landscapes" -t "your-template-uuid" ``` ### 图生图 (img2img) 基于现有图像重绘或风格转换。 **特有参数：** ``` -S, --source-image <url|path> 源图 URL 或本地路径（支持自动上传） -d, --denoising-strength <0.75> 重绘幅度 (0-1, 越高变化越大) --resize-mode <0> 缩放模式 (0=拉伸, 1=裁剪, 2=填充) --mask-image <url> 蒙版图（用于局部重绘） --mask-mode <0> 蒙版模式 --inpaint-area <0|1> 重绘区域 (0=全图, 1=仅蒙版) ``` **示例：** ```bash # 将照片转为油画风格（自动上传本地文件） ./bin/cli.js img2img -p "oil painting style, Van Gogh" -S ./photo.jpg -d 0.65 # 局部重绘（需要配合蒙版） ./bin/cli.js img2img -p "add a hat" -S original.png --mask-image mask.png --inpaint-area 1 ``` ### Ultra 模型 (text2img-ultra / img2img-ultra) 更高品质的生成，支持 ControlNet。 **特有参数：** ``` -a, --aspect-ratio <portrait|landscape|square> 宽高比 --controlnet-type <depth|canny|...> ControlNet 类型 --controlnet-image <url> ControlNet 参考图 ``` **示例：** ```bash # Ultra 文生图 + ControlNet ./bin/cli.js text2img-ultra -p "masterpiece, 1girl" -a portrait --controlnet-type depth --controlnet-image ref.jpg ``` ### 文件上传 (upload) 上传本地图片供后续使用。 ```bash # 简单上传 ./bin/cli.js upload ./my-image.png # 自定义文件名 ./bin/cli.js upload ./photo.jpg -n "reference" ``` 返回的 URL 可用于 img2img 或 ControlNet。 ### 异步任务管理 对于耗时较长的任务（ Ultra 模型、复杂工作流）： ```bash # 提交任务（返回 UUID） UUID=$(./bin/cli.js submit text2img -p "complex scene") # 检查状态 ./bin/cli.js status $UUID # 等待完成（自动轮询） ./bin/cli.js wait $UUID --interval 5000 --timeout 600000 ``` --- ## 典型工作流示例 ### 工作流 1：概念设计迭代 ```bash # 1. 生成多个版本的草图（不同种子） for seed in {1..5}; do ./bin/cli.js text2img -p "character design, fantasy warrior" --seed $seed -W 512 -H 512 -s 15 done # 2. 选择最佳的一张进行风格重绘 ./bin/cli.js img2img -p "watercolor painting" -S best-sketch.png -d 0.7 # 3. Ultra 提升细节 ./bin/cli.js text2img-ultra -p "high detail, refined" -a portrait --controlnet-type depth -S refined.png ``` ### 工作流 2：批量生成营销配图 ```bash # 使用脚本循环生成 for product in "咖啡杯" "笔记本" "耳机"; do ./bin/cli.js text2img -p "$product on white background, product photography" -W 1024 -H 1024 -s 25 & done wait ``` --- ## 故障排除 ### 认证失败 ``` Error: LiblibAI credentials not found ``` **解决**：确保环境变量已设置。测试： ```bash echo $LIBLIBAI_ACCESS_KEY echo $LIBLIBAI_SECRET_KEY ``` 如果为空，请在 ~/.zshrc 或当前 shell 中 export。 ### 速率限制 返回 429 错误。 **解决**：添加延迟（sleep 2-3 秒）或减少生成频率。 ### 模板 UUID 问题 某些高级功能需要平台预设的模板 UUID。 **解决**：登录 LiblibAI 网页版，在「模板」或「工作流」中创建并获取 ID。 ### 文件上传失败 ``` Error: File size exceeds limit ``` **解决**：确保文件 < 10MB，格式为 PNG/JPG/JPEG/WebP。 ### 网络超时 中国用户可能需要代理访问 international API。 **解决**：设置 `LIBLIBAI_BASE_URL` 为国内镜像（如有），或使用稳定网络。 --- ## 与其他技能集成 ### 结合 web_search 获取灵感 ```bash # 搜索当前流行设计风格 web_search "2025 UI design trends" # 用搜索结果作为提示词 ./bin/cli.js text2img -p "modern UI design, dark theme, glassmorphism" -W 1280 -H 720 ``` ### 结合 humanizer 优化提示词 ```bash # 用 humanizer 润色提示词，使结果更自然 # 先在聊天中让 humanizer 优化描述，再传入 text2img ``` ### 在自动化工作流中使用 ```bash # 示例：生成配图并写入 MEMORY.md URL=$(./bin/cli.js text2img -p "workflow diagram" -W 1200 -H 600 | grep -o 'https://[^"]*png') echo "今日生成的流程图: $URL" >> memory/$(date +%Y-%m-%d).md ``` --- ## 成本与积分 - **消耗**：每次生成消耗 2-5 积分（取决于分辨率、步数、模型） - **查询余额**：运行任意命令后，输出中的 `accountBalance` 显示剩余积分 - **充值**：在 LiblibAI 平台充值增加积分 **建议**：先用小分辨率（512x512）测试提示词，再放大生成以节省积分。 --- ## 参数参考表 | 参数 | 类型 | 默认 | 说明 | |------|------|------|------| | prompt | string | **必需** | 正向提示词，描述你想生成的图像 | | negativePrompt | string | - | 负向提示词，排除不想要的元素 | | width/height | number | 768/1024 | 图像尺寸（建议 512 的倍数） | | steps | number | 20 | 采样步数，质量与速度平衡 | | cfgScale | number | 7 | 提示词遵循度 | | sampler | number | 15 | 采样器 ID（15=DPMSolver++） | | seed | number | -1 | 随机种子（固定种子可复现结果） | | imgCount | number | 1 | 生成数量（1-4） | | templateUuid | string | - | 预设模板 ID（平台创建） | --- ## 提示词技巧 - **使用逗号分隔**：`"cat, cute, photorealistic, 8k"` - **权重语法**：`"(masterpiece:1.2)"` 提升权重 - **负面提示词**：始终添加 `"ugly, blurry, low quality, watermark"` - **风格引用**：`"by Greg Rutkowski"`、`"Studio Ghibli style"` - **质量词**：`"masterpiece, best quality, highres, 8k"` --- ## 技术细节 - **SDK**: 使用官方 `liblibai` npm 包（v0.0.11） - **API**: 兼容 OpenAI DALL-E 风格接口 - **超时**: 默认 5 分钟，可通过 `--timeout` 调整 - **轮询间隔**: 默认 3 秒检查状态 --- ## 版本历史 **v1.0.0** (2026-03-13) - 初始发布 - 完整 CLI 支持（text2img, img2img, upload, status, wait） - 优化输出格式（清晰图片链接） - 环境变量配置 --- ## 相关链接 - [LiblibAI 官网](https://liblibai.com) - [API 文档](https://liblibai.feishu.cn/wiki/UAMVw67NcifQHukf8fpccgS5n6d) - [npm 包](https://www.npmjs.com/package/liblibai) - [ClawHub skill 页面](https://clawhub.ai/skill/liblibai)（发布后） --- ## 许可 MIT License - 自由使用、修改和分发。 --- *最后更新: 2026-03-13 · 上海*

path: README.md
content: # LiblibAI Skill for OpenClaw

使用 LiblibAI 的强大图像生成能力，在 OpenClaw 中直接生成 AI 图像。

## 功能

- **文生图 (text2img)** - 从文本提示生成高质量图像
- **图生图 (img2img)** - 基于现有图像进行重绘或风格转换
- **Ultra 模型** - 使用更高品质的 Ultra 模型生成
- **ComfyUI 工作流** - 运行自定义 ComfyUI workflows
- **文件上传** - 上传本地文件供生成任务使用

## 快速开始

### 配置

设置环境变量：

```bash
export LIBLIBAI_ACCESS_KEY="your-access-key"
export LIBLIBAI_SECRET_KEY="your-secret-key"
```

### 生成图像

```bash
# 使用技能提供的 CLI
liblibai text2img -p "一只可爱的小狗" -W 1024 -H 1024 -s 20

# 上传文件
liblibai upload image.jpg

# 异步提交并等待
liblibai submit text2img -p "风景画"
liblibai wait <uuid>
```

## 参数说明

详见 SKILL.md 文档。

## 许可

MIT License


path: package-lock.json
content: {
  "name": "openclaw-skill-liblibai",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "openclaw-skill-liblibai",
      "version": "1.0.0",
      "license": "ISC",
      "dependencies": {
        "commander": "^14.0.3",
        "liblibai": "^0.0.11"
      },
      "bin": {
        "liblibai": "bin/cli.js"
      }
    },
    "node_modules/commander": {
      "version": "14.0.3",
      "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=20"
      }
    },
    "node_modules/liblibai": {
      "version": "0.0.11",
      "resolved": "https://registry.npmjs.org/liblibai/-/liblibai-0.0.11.tgz",
      "integrity": [REDACTED_SECRET],
      "license": "MIT",
      "engines": {
        "node": ">=14.0.0"
      }
    }
  }
}


path: package.json
content: {
  "name": "liblibai",
  "version": "1.0.0",
  "description": "OpenClaw skill for LiblibAI image generation",
  "main": "lib/client.js",
  "bin": {
    "liblibai": "./bin/cli.js"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": ["openclaw", "skill", "liblibai", "image-generation"],
  "author": "",
  "license": "MIT",
  "type": "commonjs",
  "dependencies": {
    "commander": "^14.0.3",
    "liblibai": "^0.0.11"
  }
}


path: lib/client.js
content: const { LiblibAI } = require('liblibai');

class LiblibAIClient {
  constructor(options = {}) {
    this.accessKey = options.accessKey || process.env.LIBLIBAI_ACCESS_KEY;
    this.secretKey = options.secretKey || process.env.LIBLIBAI_SECRET_KEY;
    this.baseURL = options.baseURL || process.env.LIBLIBAI_BASE_URL || 'https://openapi.liblibai.cloud';

    if (!this.accessKey || !this.secretKey) {
      throw new Error('LiblibAI credentials not found. Set LIBLIBAI_ACCESS_KEY and LIBLIBAI_SECRET_KEY environment variables or pass them as options.');
    }

    this.client = new LiblibAI({
      [REDACTED_SECRET],
      apiSecret: this.secretKey,
      baseURL: this.baseURL,
    });
  }

  async text2img(params) {
    return this.client.text2img(params);
  }

  async text2imgUltra(params) {
    return this.client.text2imgUltra(params);
  }

  async img2img(params) {
    return this.client.img2img(params);
  }

  async img2imgUltra(params) {
    return this.client.img2imgUltra(params);
  }

  async runComfy(params) {
    return this.client.runComfy(params);
  }

  async uploadFile(fileBuffer, filename = null) {
    return this.client.uploadFile(fileBuffer, filename);
  }

  async submitText2Img(params) {
    return this.client.submitText2Img(params);
  }

  async getStatus(generateUuid) {
    return this.client.getStatus(generateUuid);
  }

  async waitResult(generateUuid, pollingInterval = 3000, timeout = 300000) {
    return this.client.waitResult(generateUuid, pollingInterval, timeout);
  }

  async getComfyStatus(generateUuid) {
    return this.client.getComfyStatus(generateUuid);
  }

  async waitAppResult(generateUuid, pollingInterval = 3000, timeout = 300000) {
    return this.client.waitAppResult(generateUuid, pollingInterval, timeout);
  }
}

module.exports = { LiblibAIClient };


path: bin/cli.js
content: #!/usr/bin/env node

const { LiblibAIClient } = require('../lib/client');
const fs = require('fs');
const path = require('path');

// 简单的参数解析
function parseOptions(arr) {
  const options = {};
  for (let i = 0; i < arr.length; i++) {
    if (arr[i].startsWith('-')) {
      let key = arr[i].replace(/^-+/, '');
      if (key.includes('=')) {
        const [k, v] = key.split('=');
        options[k] = v;
      } else {
        // 检查是否是需要值的选项
        if (['p', 'prompt', 'n', 'negative-prompt', 'W', 'width', 'H', 'height',
             's', 'steps', 'c', 'cfg-scale', 'sampler', 'seed', 'i', 'img-count',
             't', 'template-uuid', 'S', 'source-image', 'd', 'denoising-strength',
             'resize-mode', 'mask-image', 'mask-mode', 'inpaint-area',
             'additional-network', 'controlnet', 'hires-steps', 'hires-denoising',
             'hires-upscaler', 'hires-width', 'hires-height', 'controlnet-type',
             'controlnet-image', 'aspect-ratio', 'a', 'randn-source', 'restore-faces'].includes(key)
            || key.startsWith('hires-') || key.startsWith('controlnet-')) {
          // 下一个参数是值
          options[key] = arr[i + 1];
          i++;
        } else {
          // 布尔标记
          options[key] = true;
        }
      }
    }
  }
  return options;
}

// 格式化输出，便于复制
function formatResult(result) {
  // 提取关键信息
  const output = [];

  if (result.generateUuid) {
    output.push(`UUID: ${result.generateUuid}`);
  }

  if (result.images && result.images.length > 0) {
    output.push('生成的图片:');
    result.images.forEach((img, idx) => {
      output.push(`[${idx + 1}] ${img.imageUrl}`);
    });
  }

  if (result.videos && result.videos.length > 0) {
    output.push('生成的视频:');
    result.videos.forEach((vid, idx) => {
      output.push(`[${idx + 1}] ${vid.videoUrl}`);
    });
  }

  // 状态信息
  output.push(`状态: ${result.generateStatus} (${getStatusText(result.generateStatus)})`);
  if (result.percentCompleted) {
    output.push(`进度: ${result.percentCompleted}%`);
  }

  // 费用信息
  if (result.pointsCost !== undefined) {
    output.push(`消耗积分: ${result.pointsCost}`);
  }
  if (result.accountBalance !== undefined) {
    output.push(`剩余积分: ${result.accountBalance}`);
  }

  return output.join('\n');
}

function getStatusText(status) {
  const statusMap = {
    1: '待处理',
    2: '处理中',
    3: '已生成',
    4: '审核中',
    5: '成功',
    6: '失败',
    7: '超时'
  };
  return statusMap[status] || '未知';
}

// 简化的 CLI
async function main() {
  const args = process.argv.slice(2);
  const command = args[0];

  if (!command || command === '--help' || command === '-h') {
    console.log(`
liblibai - LiblibAI 图像生成命令行工具

用法:
  liblibai <command> [options]

命令:
  text2img           从文本生成图像
  text2img-ultra     使用 Ultra 模型生成图像
  img2img            基于现有图像生成新图像
  upload <file>      上传本地文件到 LiblibAI
  status <uuid>      检查任务状态
  wait <uuid>        等待任务完成并获取结果

示例:
  liblibai text2img -p "一只可爱的小狗" -W 1024 -H 1024
  liblibai upload image.jpg
  liblibai wait <uuid>
    `);
    return;
  }

  const options = parseOptions(args.slice(1));

  try {
    const client = new LiblibAIClient();

    switch (command) {
      case 'text2img':
        if (!options.p) {
          console.error('错误: 必须提供 -p/--prompt 参数');
          process.exit(1);
        }

        const params = {
          templateUuid: options.t,
          generateParams: {
            width: parseInt(options.W) || 768,
            height: parseInt(options.H) || 1024,
            steps: parseInt(options.s) || 20,
            cfgScale: parseFloat(options.c) || 7,
            sampler: parseInt(options.sampler) || 15,
            seed: parseInt(options.seed) || -1,
            imgCount: parseInt(options.i) || 1,
            randnSource: parseInt(options['randn-source']) || 0,
            restoreFaces: parseInt(options['restore-faces']) || 0,
            prompt: options.p,
            negativePrompt: options.n,
          }
        };

        if (options['additional-network']) {
          params.generateParams.additionalNetwork = JSON.parse(options['additional-network']);
        }

        if (options.hires) {
          params.generateParams.hiResFixInfo = {
            hiresSteps: parseInt(options['hires-steps']) || 20,
            hiresDenoisingStrength: parseFloat(options['hires-denoising']) || 0.75,
            upscaler: parseInt(options['hires-upscaler']) || 10,
          };
          if (options['hires-width'] && options['hires-height']) {
            params.generateParams.hiResFixInfo.resizedWidth = parseInt(options['hires-width']);
            params.generateParams.hiResFixInfo.resizedHeight = parseInt(options['hires-height']);
          }
        }

        if (options.controlnet) {
          params.generateParams.controlNet = JSON.parse(options.controlnet);
        }

        console.log('正在生成图像...');
        const result = await client.text2img(params);
        console.log('\n' + formatResult(result) + '\n');
        break;

      case 'upload':
        const file = args[1];
        if (!file) {
          console.error('错误: 必须提供文件路径');
          process.exit(1);
        }
        if (!fs.existsSync(file)) {
          console.error('错误: 文件不存在:', file);
          process.exit(1);
        }
        const fileBuffer = fs.readFileSync(file);
        const filename = options.name || path.basename(file);
        console.log(`正在上传 ${filename}...`);
        const uploadResult = await client.uploadFile(fileBuffer, filename);
        console.log('上传成功:', uploadResult);
        break;

      case 'status':
        const uuid = args[1];
        if (!uuid) {
          console.error('错误: 必须提供 UUID');
          process.exit(1);
        }
        const statusResult = await client.getStatus(uuid);
        console.log('\n' + formatResult(statusResult) + '\n');
        break;

      case 'wait':
        const waitUuid = args[1];
        if (!waitUuid) {
          console.error('错误: 必须提供 UUID');
          process.exit(1);
        }
        const interval = parseInt(options.interval) || 3000;
        const timeout = parseInt(options.timeout) || 300000;
        console.log('等待任务完成...');
        const waitResult = await client.waitResult(waitUuid, interval, timeout);
        console.log('\n' + formatResult(waitResult) + '\n');
        break;

      default:
        console.error(`未知命令: ${command}`);
        process.exit(1);
    }
  } catch (error) {
    console.error('错误:', error.message);
    process.exit(1);
  }
}

main();


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (MEDIUM)