Skill: kongweigen/huobao-image-generation (version 1.0.2)

# AI 火宝 🔥 火山引擎 AI 生图 Skill。支持多种模型。 ## 环境变量 ```bash export HUOBAO_API_KEY="<your-api-key>" ``` 或使用 `--api-key` 参数传入。 ## 支持的模型 | 模型 | 说明 | |------|------| | `gemini-2.5-flash-image` | Gemini 2.5 Flash Image | | `gemini-2.5-flash-image-preview` | Gemini 2.5 Flash Image Preview | | `nano-banana` | Nano Banana | | `nano-banana-pro` | Nano Banana Pro | | `nano-banana-pro_4k` | Nano Banana Pro 4K | | `doubao-seedream-4-5-251128` | 豆包 Seedream 4.5 | ## 支持的尺寸 | 尺寸 | 说明 | |------|------| | `1x1` | 正方形 | | `16x9` | 宽屏 | | `9x16` | 竖屏 | | `3x4` | 竖屏 | | `4x3` | 宽屏 | ## 功能 ### 文生图 (text2image) ```bash python3 scripts/t2i.py "提示词" --model nano-banana-pro --size 1x1 ``` ### 图生图 (image2image) ```bash python3 scripts/i2i.py --image <图片URL> --prompt "描述" --model nano-banana-pro ``` ## 参数 | 参数 | 说明 | |------|------| | `prompt` | 提示词（必填） | | `--model` | 模型名称（默认: nano-banana-pro） | | `--size` | 尺寸（默认: 1x1） | | `--count` | 生成数量 1-4 (默认: 1) | | `--watermark` | 是否添加水印 (默认: true) | | `--api-key` | API Key（必填） | | `--debug` | 调试模式 | ## 示例 ```bash # 文生图 - Nano Banana Pro python3 scripts/t2i.py "一只可爱的猫咪" --model nano-banana-pro --size 1x1 --api-key "sk-xxx" # 文生图 - Gemini 2.5 Flash python3 scripts/t2i.py "风景画" --model gemini-2.5-flash-image --size 16x9 --api-key "sk-xxx" # 图生图 python3 scripts/i2i.py --image "https://example.com/img.jpg" --prompt "动漫风格" --model nano-banana-pro --api-key "sk-xxx" ``` ## 输出格式 成功返回 JSON： ```json { "success": true, "prompt": "...", "model": "nano-banana-pro", "size": "1x1", "count": 1, "images": [{"url": "..."}], "usage": {...} } ```

path: _meta.json
content: {
  "name": "huobao-image-generation",
  "version": "1.0.2",
  "description": "AI 火宝 - 火山引擎 AI 生图 Skill，支持多模型",
  "metadata": {
    "openclaw": {
      "emoji": "🔥",
      "category": "ai",
      "tags": ["image", "generation", "ai", "volcengine", "huobao", "fire", "gemini", "nano-banana", "doubao"]
    }
  }
}


path: scripts/i2i.py
content: #!/usr/bin/env python3
"""
火山引擎 AI 图生图脚本
用法: python3 i2i.py --image <图片> --prompt "提示词" [选项]
"""

import argparse
import json
import os
import sys
import urllib.request
import urllib.error


API_URL = "https://api.chatfire.site/v1/images/generations"

# 支持的模型
MODELS = [
    "gemini-2.5-flash-image",
    "gemini-2.5-flash-image-preview",
    "nano-banana",
    "nano-banana-pro",
    "nano-banana-pro_4k",
    "doubao-seedream-4-5-251128"
]

# 支持的尺寸
SIZES = ["1x1", "16x9", "9x16", "3x4", "4x3"]


def get_api_key():
    """获取 API Key"""
    [REDACTED_SECRET]"HUOBAO_API_KEY")
    if not api_key:
        for i, arg in enumerate(sys.argv):
            if arg == "--api-key" and i + 1 < len(sys.argv):
                return sys.argv[i + 1]
        print("Error: 请设置环境变量 HUOBAO_API_KEY 或使用 --api-key 参数", file=sys.stderr)
        sys.exit(1)
    return api_key


def image2image(image, prompt, model="nano-banana-pro", size="1x1", count=1, watermark=True, api_key=None, debug=False):
    """图生图"""
    if api_key is None:
        [REDACTED_SECRET])
    
    # 支持本地文件或URL
    if not image.startswith("http://") and not image.startswith("https://"):
        print(f"Error: 当前版本仅支持 URL 格式的图片输入", file=sys.stderr)
        print(f"提示: 请使用图床服务将图片转为 URL", file=sys.stderr)
        sys.exit(1)
    
    # 验证模型
    if model not in MODELS:
        print(f"Warning: 模型 {model} 不在已知列表中，继续尝试...", file=sys.stderr)
    
    # 构建请求体
    body = {
        "model": model,
        "prompt": prompt,
        "image": [image],
        "response_format": "url",
        "size": size,
        "stream": False,
        "watermark": watermark
    }
    
    if count > 1:
        body["sequential_image_generation"] = "auto"
        body["sequential_image_generation_options"] = {"max_images": count}
    
    if debug:
        print(f"输入图片: {image}", file=sys.stderr)
        print(f"提示词: {prompt}", file=sys.stderr)
        print(f"模型: {model}", file=sys.stderr)
        print(f"尺寸: {size}", file=sys.stderr)
        print(f"请求体: {json.dumps(body, ensure_ascii=False)}", file=sys.stderr)
    
    # 发送请求
    req = urllib.request.Request(
        API_URL,
        data=json.dumps(body).encode("utf-8"),
        headers={
            "Content-Type": "application/json",
            "Authorization": f"Bearer {api_key}"
        },
        method="POST"
    )
    
    try:
        with urllib.request.urlopen(req, timeout=120) as response:
            result = json.loads(response.read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        error_body = e.read().decode("utf-8")
        print(f"HTTP Error {e.code}: {error_body}", file=sys.stderr)
        sys.exit(1)
    except urllib.error.URLError as e:
        print(f"Network Error: {e.reason}", file=sys.stderr)
        sys.exit(1)
    
    # 解析结果
    if "data" in result and len(result["data"]) > 0:
        images = []
        for img in result["data"]:
            images.append({
                "url": img.get("url", "")
            })
        
        output = {
            "success": True,
            "input_image": image,
            "prompt": prompt,
            "model": model,
            "size": size,
            "count": len(images),
            "images": images,
            "usage": result.get("usage", {})
        }
        print(json.dumps(output, ensure_ascii=False, indent=2))
    else:
        print(json.dumps({"success": False, "error": "No images returned"}, ensure_ascii=False, indent=2))
        sys.exit(1)


def main():
    parser = argparse.ArgumentParser(description="火山引擎 AI 图生图")
    parser.add_argument("--image", "-i", required=True, help="输入图片 URL")
    parser.add_argument("--prompt", "-p", required=True, help="图片描述/编辑提示词")
    parser.add_argument("--model", "-m", default="nano-banana-pro", help=f"模型名称 (默认: nano-banana-pro)")
    parser.add_argument("--size", "-s", default="1x1", choices=SIZES, help=f"尺寸 (默认: 1x1)")
    parser.add_argument("--count", "-c", type=int, default=1, help="生成数量 1-4 (默认: 1)")
    parser.add_argument("--watermark", "-w", type=bool, default=True, help="是否添加水印 (默认: True)")
    parser.add_argument("--api-key", "-k", help="API Key")
    parser.add_argument("--debug", "-d", action="store_true", help="调试模式")
    
    args = parser.parse_args()
    
    image2image(
        image=args.image,
        prompt=args.prompt,
        model=args.model,
        size=args.size,
        count=args.count,
        watermark=args.watermark,
        [REDACTED_SECRET],
        debug=args.debug
    )


if __name__ == "__main__":
    main()


path: scripts/t2i.py
content: #!/usr/bin/env python3
"""
火山引擎 AI 文生图脚本
用法: python3 t2i.py "提示词" [选项]
"""

import argparse
import json
import os
import sys
import urllib.request
import urllib.error


API_URL = "https://api.chatfire.site/v1/images/generations"

# 支持的模型
MODELS = [
    "gemini-2.5-flash-image",
    "gemini-2.5-flash-image-preview",
    "nano-banana",
    "nano-banana-pro",
    "nano-banana-pro_4k",
    "doubao-seedream-4-5-251128"
]

# 支持的尺寸
SIZES = ["1x1", "16x9", "9x16", "3x4", "4x3"]


def get_api_key():
    """获取 API Key"""
    [REDACTED_SECRET]"HUOBAO_API_KEY")
    if not api_key:
        # 尝试从参数获取
        for i, arg in enumerate(sys.argv):
            if arg == "--api-key" and i + 1 < len(sys.argv):
                return sys.argv[i + 1]
        print("Error: 请设置环境变量 HUOBAO_API_KEY 或使用 --api-key 参数", file=sys.stderr)
        sys.exit(1)
    return api_key


def text2image(prompt, model="nano-banana-pro", size="1x1", count=1, watermark=True, api_key=None, debug=False):
    """文生图"""
    if api_key is None:
        [REDACTED_SECRET])
    
    # 验证模型
    if model not in MODELS:
        print(f"Warning: 模型 {model} 不在已知列表中，继续尝试...", file=sys.stderr)
    
    # 构建请求体
    body = {
        "model": model,
        "prompt": prompt,
        "response_format": "url",
        "size": size,
        "stream": False,
        "watermark": watermark
    }
    
    if count > 1:
        body["sequential_image_generation"] = "auto"
        body["sequential_image_generation_options"] = {"max_images": count}
    
    if debug:
        print(f"提示词: {prompt}", file=sys.stderr)
        print(f"模型: {model}", file=sys.stderr)
        print(f"尺寸: {size}", file=sys.stderr)
        print(f"数量: {count}", file=sys.stderr)
        print(f"请求体: {json.dumps(body, ensure_ascii=False)}", file=sys.stderr)
    
    # 发送请求
    req = urllib.request.Request(
        API_URL,
        data=json.dumps(body).encode("utf-8"),
        headers={
            "Content-Type": "application/json",
            "Authorization": f"Bearer {api_key}"
        },
        method="POST"
    )
    
    try:
        with urllib.request.urlopen(req, timeout=120) as response:
            result = json.loads(response.read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        error_body = e.read().decode("utf-8")
        print(f"HTTP Error {e.code}: {error_body}", file=sys.stderr)
        sys.exit(1)
    except urllib.error.URLError as e:
        print(f"Network Error: {e.reason}", file=sys.stderr)
        sys.exit(1)
    
    # 解析结果
    if "data" in result and len(result["data"]) > 0:
        images = []
        for img in result["data"]:
            images.append({
                "url": img.get("url", "")
            })
        
        output = {
            "success": True,
            "prompt": prompt,
            "model": model,
            "size": size,
            "count": len(images),
            "images": images,
            "usage": result.get("usage", {})
        }
        print(json.dumps(output, ensure_ascii=False, indent=2))
    else:
        print(json.dumps({"success": False, "error": "No images returned"}, ensure_ascii=False, indent=2))
        sys.exit(1)


def main():
    parser = argparse.ArgumentParser(description="火山引擎 AI 文生图")
    parser.add_argument("prompt", help="图片描述提示词")
    parser.add_argument("--model", "-m", default="nano-banana-pro", help=f"模型名称 (默认: nano-banana-pro)")
    parser.add_argument("--size", "-s", default="1x1", choices=SIZES, help=f"尺寸 (默认: 1x1)")
    parser.add_argument("--count", "-c", type=int, default=1, help="生成数量 1-4 (默认: 1)")
    parser.add_argument("--watermark", "-w", type=bool, default=True, help="是否添加水印 (默认: True)")
    parser.add_argument("--api-key", "-k", help="API Key")
    parser.add_argument("--debug", "-d", action="store_true", help="调试模式")
    
    args = parser.parse_args()
    
    text2image(
        prompt=args.prompt,
        model=args.model,
        size=args.size,
        count=args.count,
        watermark=args.watermark,
        [REDACTED_SECRET],
        debug=args.debug
    )


if __name__ == "__main__":
    main()


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