Skill: kevin-chen2026/bizyair-banana2 (version 1.0.0)

--- name: bizyair-banana2 description: 使用 BizyAir API 和 Nano Banana 2 模型生成图片。支持参考图、表情包生成。按量付费，无需本地 GPU。 --- # BizyAir Banana 2 图像生成 直接调用 BizyAir API，使用 Nano Banana 2 模型生成高质量图片。 ## 前置要求 ### 1. 注册 BizyAir 账号 - 访问 https://www.bizyair.cn 注册账号 ### 2. 获取 API Key - 登录后进入控制台复制 API Key ### 3. 配置 API Key（二选一） **方式 A：环境变量** ```bash export BIZYAIR_API_KEY="your_api_key_here" ``` **方式 B：创建配置文件（推荐）** 在技能目录创建 `.env` 文件： ```bash # 技能目录/.env BIZYAIR_API_KEY=your_api_key_here ``` **配置文件位置优先级：** 1. 技能目录下的 `.env`（推荐，通用） 2. `~/.config/bizyair-banana2/.env` 3. `~/.bizyair-banana2/.env` 4. `~/.baoyu-skills/bizyair-banana2/.env`（兼容旧版本） ## 使用方法 ### 基础用法 - 文生图 ```bash python3 ${SKILL_DIR}/scripts/bizyair_gen.py \ --prompt "一只可爱的猫咪" \ --image cat.png ``` ### 使用参考图（图生图） ```bash python3 ${SKILL_DIR}/scripts/bizyair_gen.py \ --prompt "近景构图，自信展示自我，姿态酷飒随性" \ --image output.png \ --ref input.png ``` ### 多张参考图 ```bash python3 ${SKILL_DIR}/scripts/bizyair_gen.py \ --prompt "图 1 的人穿着图 2 的衣服，在图 3 的场景中" \ --image output.png \ --ref person.png \ --ref clothes.png \ --ref background.png ``` ### 指定宽高比 ```bash python3 ${SKILL_DIR}/scripts/bizyair_gen.py \ --prompt "全身照" \ --image fullbody.png \ --ar 9:16 ``` ### 表情包生成（Web App 47091） ```bash python3 ${SKILL_DIR}/scripts/bizyair_gen.py \ --prompt "搞笑表情" \ --image emoji.png \ --ref portrait.jpg \ --web-app-id 47091 ``` ## 命令行选项 | 选项 | 说明 | 默认值 | |------|------|--------| | `-p, --prompt` | 提示词（必需） | - | | `-i, --image` | 输出图片路径（必需） | - | | `-r, --ref` | 参考图片路径（可多个） | - | | `--web-app-id` | Web App ID | 47091 | | `--ar` | 宽高比：`1:1`, `16:9`, `9:16`, `4:3`, `3:4` | `9:16` | | `--mode` | 模式：`third-party`, `custom` | `third-party` | | `--resolution` | 分辨率：`auto`, `1k`, `2k` | `1k` | | `--timeout` | 超时时间（秒） | 120 | | `--json` | JSON 格式输出 | - | ## 环境变量 | 变量 | 说明 | |------|------| | `BIZYAIR_API_KEY` | BizyAir API Key（必需） | | `BIZYAIR_BASE_URL` | API 基础 URL（可选） | ## 计费说明 - 按量付费，生成成功才扣费 - 具体价格：https://docs.bizyair.cn/pricing/introduce.html ## API 参考 - 任务提交：`POST /w/v1/webapp/task/openapi/create` - 状态查询：`GET /w/v1/webapp/task/openapi/detail?requestId={id}` - 结果获取：`GET /w/v1/webapp/task/openapi/outputs?requestId={id}` - 文件上传：`GET /x/v1/upload/token` ## 错误处理 | 错误 | 原因 | 解决方案 | |------|------|----------| | `401 Unauthorized` | API Key 无效 | 检查 BIZYAIR_API_KEY 配置 | | `402 Payment Required` | 余额不足 | 充值：https://www.bizyair.cn | | `429 Too Many Requests` | 请求限流 | 稍后重试 | | `500 Internal Error` | 服务端错误 | 检查任务状态，重试 | ## 示例工作流 ### 示例 1：生成头像 ```bash python3 ${SKILL_DIR}/scripts/bizyair_gen.py \ -p "可爱的卡通女孩头像，粉色头发，大眼睛" \ --image avatar.png \ --ar 1:1 ``` ### 示例 2：生成表情包（使用参考图） ```bash python3 ${SKILL_DIR}/scripts/bizyair_gen.py \ -p "搞笑表情，九宫格" \ --image meme.png \ --ref portrait.jpg \ --web-app-id 47091 ``` ### 示例 3：多参考图融合 ```bash python3 ${SKILL_DIR}/scripts/bizyair_gen.py \ -p "图 1 的人穿着图 2 的衣服，在图 3 的场景中" \ --image fusion.png \ --ref person.png \ --ref clothes.png \ --ref background.png \ --ar 9:16 ``` ### 示例 4：批量生成 ```bash for i in {1..5}; do python3 ${SKILL_DIR}/scripts/bizyair_gen.py \ -p "赛博朋克风格城市夜景" \ --image cyber_$i.png \ --ar 16:9 done ``` ## 参考资料 - [BizyAir 官网](https://www.bizyair.cn) - [BizyAir 文档](https://docs.bizyair.cn) - [API 参考](https://docs.bizyair.cn/api/api-reference.html) - [工作流广场](https://www.bizyair.cn/workflows) - [模型广场](https://www.bizyair.cn/models) ## 故障排查 ### 1. 检查 API Key ```bash # 方式 1：检查技能目录的.env cat /path/to/skills/bizyair-banana2/.env # 方式 2：检查用户目录配置 cat ~/.config/bizyair-banana2/.env cat ~/.bizyair-banana2/.env ``` ### 2. 运行测试 ```bash cd /home/admin/.openclaw/workspace/skills/bizyair-banana2 bash test.sh ``` ### 3. 常见错误 | 错误 | 原因 | 解决方案 | |------|------|----------| | `401 Unauthorized` | API Key 无效 | 检查配置 | | `402 Payment Required` | 余额不足 | 充值 | | `429 Too Many Requests` | 请求限流 | 稍后重试 | | 任务超时 | 生成耗时过长 | 增加 `--timeout` | ## 限制 - 图片生成需通过内容审核 - 参考图大小不超过 10MB - 支持格式：PNG, JPG, WEBP

path: CONFIG.md
content: # BizyAir Banana 2 配置指南

## ⚙️ API Key 配置

### 方式 1：.env 文件（推荐）

在技能目录创建 `.env` 文件：
```bash
BIZYAIR_API_KEY=你的_API_Key
```

### 方式 2：环境变量

```bash
export BIZYAIR_API_KEY="你的_API_Key"
```

---

## 📁 配置文件位置

优先级从高到低：

1. `技能目录/.env` ⭐ 推荐
2. `~/.config/bizyair-banana2/.env`
3. `~/.bizyair-banana2/.env`

---

## ✅ 验证配置

```bash
python3 scripts/bizyair_gen.py --help
```

显示帮助信息即配置成功。

---

## 🔧 可选配置

编辑 `.env` 文件：
```bash
# API Key（必需）
BIZYAIR_API_KEY=你的_API_Key

# 基础 URL（可选）
# BIZYAIR_BASE_URL=https://api.bizyair.cn
```

---

## ❓ 故障排查

### 提示"未配置 BIZYAIR_API_KEY"

**检查：**
1. `.env` 文件是否存在
2. `.env` 文件格式：`BIZYAIR_API_KEY=xxx`（无空格）
3. API Key 是否正确

### 生成失败

**检查：**
1. API Key 是否有效
2. 余额是否充足
3. 提示词是否合规

---

*配置指南 | 2026-04-03*


path: package.json
content: {
  "name": "bizyair-banana2",
  "version": "1.0.0",
  "description": "BizyAir Banana 2 图像生成技能",
  "main": "scripts/main.ts",
  "type": "module",
  "scripts": {
    "start": "bun scripts/main.ts"
  },
  "dependencies": {}
}


path: README.md
content: # BizyAir Banana 2 图像生成技能

使用 BizyAir API 和 Nano Banana 2 模型生成高质量图片。支持参考图、表情包生成。按量付费，无需本地 GPU。

---

## 🚀 快速开始

### 1. 获取 API Key

访问 https://www.bizyair.cn 注册账号并获取 API Key

### 2. 配置 API Key

**方式 A：创建.env 文件（推荐）**

在技能目录创建 `.env` 文件：
```bash
BIZYAIR_API_KEY=你的_API_Key
```

**方式 B：环境变量**
```bash
export BIZYAIR_API_KEY="你的_API_Key"
```

### 3. 开始生成

```bash
python3 scripts/bizyair_gen.py \
  --prompt "一只可爱的猫咪" \
  --image cat.png
```

---

## 💡 使用示例

### 文生图

```bash
python3 scripts/bizyair_gen.py \
  --prompt "一只可爱的猫咪" \
  --image cat.png \
  --ar 1:1
```

### 参考图生图

```bash
python3 scripts/bizyair_gen.py \
  --prompt "变成卡通风格" \
  --image output.png \
  --ref input.png
```

### 表情包生成

```bash
python3 scripts/bizyair_gen.py \
  --prompt "搞笑表情" \
  --image emoji.png \
  --ref portrait.jpg \
  --web-app-id 47091
```

---

## 📋 参数说明

| 参数 | 说明 | 默认值 |
|------|------|--------|
| `-p, --prompt` | 提示词（必需） | - |
| `-i, --image` | 输出路径（必需） | - |
| `-r, --ref` | 参考图（可多个） | - |
| `--ar` | 宽高比 | `9:16` |
| `--resolution` | 分辨率 | `1k` |
| `--web-app-id` | Web App ID | `47091` |
| `--timeout` | 超时时间 | `120` |

---

## 💰 费用说明

- **1K 分辨率**：5 分钱/张
- **2K/4K 分辨率**：8 分钱/张
- **参考图**：同分辨率价格
- **按量付费**：生成成功才扣费

---

## ❓ 常见问题

### Q: API Key 在哪里配置？

**A:** 在技能目录创建 `.env` 文件：
```bash
BIZYAIR_API_KEY=你的_API_Key
```

### Q: 支持哪些宽高比？

**A:** `1:1`, `16:9`, `9:16`, `3:4`, `4:3`, `21:9` 等

### Q: 生成失败怎么办？

**A:** 检查：
1. API Key 是否正确
2. 余额是否充足
3. 提示词是否合规

---

## 🔗 相关链接

- **官网：** https://www.bizyair.cn
- **文档：** https://docs.bizyair.cn
- **价格：** https://docs.bizyair.cn/pricing/introduce.html

---

*版本：1.0.0 | 更新时间：2026-04-03*


path: README_SHARE.md
content: # BizyAir Banana 2 分享包

## 📦 分享包内容

- ✅ 完整技能文件
- ✅ 使用文档
- ✅ 配置模板
- ❌ 不含 API Key
- ❌ 不含参考图

---

## 🚀 安装步骤

### 1. 解压

```bash
cd ~/.openclaw/workspace/skills/
tar -xzf bizyair-banana2-share.tar.gz
```

### 2. 配置 API Key

```bash
cd bizyair-banana2/
cp .env.example .env
# 编辑 .env 填入你的 API Key
```

### 3. 测试

```bash
python3 scripts/bizyair_gen.py --help
```

---

## 💡 快速使用

```bash
# 文生图
python3 scripts/bizyair_gen.py \
  --prompt "一只可爱的猫咪" \
  --image cat.png

# 参考图生图
python3 scripts/bizyair_gen.py \
  --prompt "变成卡通风格" \
  --image output.png \
  --ref input.png
```

---

## 📋 配置说明

**API Key 配置位置（优先级从高到低）：**

1. `技能目录/.env` ⭐ 推荐
2. `~/.config/bizyair-banana2/.env`
3. `~/.bizyair-banana2/.env`

---

## 💰 费用

- 1K 分辨率：5 分钱/张
- 2K/4K 分辨率：8 分钱/张
- 按量付费，生成成功才扣费

---

## 🔗 获取 API Key

访问 https://www.bizyair.cn 注册并获取

---

*分享包版本：1.0.0 | 2026-04-03*


path: test.sh
content: #!/bin/bash
# 快速测试脚本

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PYTHON_SCRIPT="$SCRIPT_DIR/scripts/bizyair_gen.py"

echo "🧪 BizyAir Banana 2 测试"
echo "======================"
echo ""

# 检查 API Key
if [ -z "$BIZYAIR_API_KEY" ]; then
    echo "⚠️  未设置 BIZYAIR_API_KEY 环境变量"
    echo ""
    echo "请先配置："
    echo "  export BIZYAIR_API_KEY=\"your_key\""
    echo ""
    echo "或创建配置文件："
    echo "  cp $SCRIPT_DIR/.env.example $SCRIPT_DIR/.env"
    echo "  编辑 .env 填入 API Key"
    echo ""
    exit 1
fi

# 测试命令
echo "运行测试命令..."
echo ""

python3 "$PYTHON_SCRIPT" \
    --prompt "测试生成，高质量，细节丰富" \
    --image "$SCRIPT_DIR/test_output.png" \
    --ar 1:1 \
    --timeout 60 \
    --json

echo ""
echo "✅ 测试完成！"


path: _meta.json
content: {
  "name": "bizyair-banana2",
  "version": "1.0.0",
  "description": "使用 BizyAir 云端 ComfyUI 和 Nano Banana 2 模型生成图片",
  "author": "小钳宝",
  "license": "MIT",
  "skills": ["image-generation", "bizyair", "banana2"],
  "triggers": ["生成图片", "画", "BizyAir", "Banana", "表情包"],
  "runtime": "bun"
}


path: scripts/bizyair_gen.py
content: #!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
BizyAir Banana 2 图像生成脚本
使用 BizyAir API 直接调用 Nano Banana 2 模型
支持文生图、图生图、表情包生成
"""

import requests
import json
import sys
import os
import time
import argparse
from datetime import datetime

# 配置
BIZYAIR_BASE_URL = "https://api.bizyair.cn"
BIZYAIR_API_KEY = os.environ.get("BIZYAIR_API_KEY")

# 默认工作流配置（从用户提供的示例）
DEFAULT_WEB_APP_ID = 47091  # Nano Banana 2 表情包生成

def get_api_key():
    """获取 API Key"""
    # 优先级：环境变量 > 技能目录.env > 用户目录.env > 报错
    if BIZYAIR_API_KEY:
        return BIZYAIR_API_KEY
    
    # 尝试从配置文件读取（通用路径）
    script_dir = os.path.dirname(os.path.abspath(__file__))
    skill_dir = os.path.dirname(script_dir)
    
    config_paths = [
        # 优先使用技能目录下的.env（最通用）
        os.path.join(skill_dir, ".env"),
        # 兼容旧版本：脚本同目录
        os.path.join(script_dir, ".env"),
        # 用户目录配置（可选）
        os.path.expanduser("~/.config/bizyair-banana2/.env"),
        os.path.expanduser("~/.bizyair-banana2/.env"),
        # 兼容 baoyu 用户（如果有）
        os.path.expanduser("~/.baoyu-skills/bizyair-banana2/.env"),
    ]
    
    for path in config_paths:
        if os.path.exists(path):
            with open(path, 'r') as f:
                for line in f:
                    if line.startswith("BIZYAIR_API_KEY="):
                        return line.split("=", 1)[1].strip()
    
    return None

def upload_file(file_path):
    """
    上传文件到 BizyAir OSS
    返回 OSS URL
    """
    import base64
    import hmac
    import hashlib
    from urllib.parse import quote
    
    if not os.path.exists(file_path):
        raise FileNotFoundError(f"文件不存在：{file_path}")
    
    file_name = os.path.basename(file_path)
    print(f"📤 上传文件：{file_name}")
    
    # 步骤 1: 获取上传凭证
    token_url = f"{BIZYAIR_BASE_URL}/x/v1/upload/token"
    params = {
        "file_name": file_name,
        "file_type": "inputs"
    }
    headers = {
        "Authorization": f"Bearer {api_key}"
    }
    
    response = requests.get(token_url, params=params, headers=headers, timeout=30)
    if response.status_code != 200:
        raise Exception(f"获取上传凭证失败：{response.status_code} {response.text}")
    
    token_data = response.json()
    if not token_data.get("status"):
        raise Exception(f"获取上传凭证失败：{token_data.get('message')}")
    
    file_info = token_data["data"]["file"]
    storage_info = token_data["data"]["storage"]
    
    object_key = file_info['object_key']
    [REDACTED_SECRET]'access_key_id']
    [REDACTED_SECRET]'access_key_secret']
    security_token = file_info['security_token']
    bucket = storage_info['bucket']
    endpoint = storage_info['endpoint']
    
    # 步骤 2: 构造 Policy
    import datetime
    expiration = datetime.datetime.utcnow() + datetime.timedelta(hours=1)
    expiration_str = expiration.strftime('%Y-%m-%dT%H:%M:%SZ')
    
    policy_dict = {
        "expiration": expiration_str,
        "conditions": [
            {"bucket": bucket},
            ["starts-with", "$key", "inputs/"],
            {"x-oss-security-token": security_token},
        ]
    }
    
    policy_base64 = base64.b64encode(json.dumps(policy_dict).encode()).decode()
    
    # 计算 Signature
    signature = base64.b64encode(
        hmac.new(access_key_secret.encode(), policy_base64.encode(), hashlib.sha1).digest()
    ).decode()
    
    # 步骤 3: 上传到 OSS
    oss_url = f"https://{bucket}.{endpoint}"
    
    files = {
        'file': (file_name, open(file_path, 'rb'), 'image/png' if file_name.endswith('.png') else 'image/jpeg')
    }
    
    oss_data = {
        'key': object_key,
        'OSSAccessKeyId': access_key_id,
        'policy': policy_base64,
        'Signature': signature,
        'x-oss-security-token': security_token,
    }
    
    response = requests.post(oss_url, data=oss_data, files=files, timeout=60)
    if response.status_code != 204:
        raise Exception(f"OSS 上传失败：{response.status_code} {response.text}")
    
    print(f"✅ OSS 上传成功")
    
    # 步骤 4: 提交输入资源
    commit_url = f"{BIZYAIR_BASE_URL}/x/v1/input_resource/commit"
    commit_data = {
        "name": file_name,
        "object_key": object_key
    }
    
    response = requests.post(commit_url, json=commit_data, headers=headers, timeout=30)
    if response.status_code != 200:
        raise Exception(f"提交资源失败：{response.status_code} {response.text}")
    
    commit_result = response.json()
    if not commit_result.get("status"):
        raise Exception(f"提交资源失败：{commit_result.get('message')}")
    
    file_url = commit_result["data"]["url"]
    print(f"✅ 上传成功：{file_url}")
    
    return file_url

def submit_task(web_app_id, input_values, suppress_preview=False, timeout=120):
    """
    提交生成任务
    
    Args:
        web_app_id: Web 应用 ID（如 47091）
        input_values: 输入值字典，格式如 {"2:LoadImage.image": "url", ...}
        suppress_preview: 是否禁用预览
        timeout: 超时时间（秒）
    
    Returns:
        request_id: 任务 ID
    """
    url = f"{BIZYAIR_BASE_URL}/w/v1/webapp/task/openapi/create"
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {api_key}"
    }
    
    data = {
        "web_app_id": web_app_id,
        "suppress_preview_output": suppress_preview,
        "input_values": input_values
    }
    
    print(f"🚀 提交任务到 Web App {web_app_id}...")
    response = requests.post(url, headers=headers, json=data, timeout=timeout)
    
    result = response.json()
    
    # 处理两种响应模式：
    # 1. 异步模式 (202): 返回 requestId
    # 2. 同步模式 (200): 直接返回完整结果
    if response.status_code == 202:
        request_id = result.get("requestId")
        print(f"📋 请求 ID: {request_id}")
        return request_id
    elif response.status_code == 200:
        # 同步模式，直接返回结果
        if result.get("status") == "Success":
            print(f"✅ 任务已完成！")
            request_id = result.get("request_id")
            # 直接保存输出
            outputs = result.get("outputs", [])
            if outputs:
                print(f"📊 输出数量：{len(outputs)}")
                return request_id
            return request_id
        else:
            raise Exception(f"任务失败：{result}")
    else:
        error_text = response.text
        raise Exception(f"提交任务失败：{response.status_code} {error_text}")

def query_task_status(request_id):
    """查询任务状态"""
    url = f"{BIZYAIR_BASE_URL}/w/v1/webapp/task/openapi/detail"
    params = {"requestId": request_id}
    headers = {
        "Authorization": f"Bearer {api_key}"
    }
    
    response = requests.get(url, params=params, headers=headers, timeout=30)
    if response.status_code != 200:
        raise Exception(f"查询状态失败：{response.status_code}")
    
    result = response.json()
    return result.get("data", {})

def get_task_outputs(request_id):
    """获取任务输出"""
    url = f"{BIZYAIR_BASE_URL}/w/v1/webapp/task/openapi/outputs"
    params = {"requestId": request_id}
    headers = {
        "Authorization": f"Bearer {api_key}"
    }
    
    response = requests.get(url, params=params, headers=headers, timeout=30)
    if response.status_code != 200:
        raise Exception(f"获取结果失败：{response.status_code}")
    
    result = response.json()
    return result.get("data", {}).get("outputs", [])

def wait_for_task(request_id, timeout=120, poll_interval=2):
    """
    轮询等待任务完成
    
    Args:
        request_id: 任务 ID
        timeout: 超时时间（秒）
        poll_interval: 轮询间隔（秒）
    
    Returns:
        任务状态数据
    """
    start_time = time.time()
    
    # 如果没有 request_id，返回空结果
    if not request_id:
        print("⚠️ 无任务 ID，跳过等待")
        return {"status": "Success", "outputs": []}
    
    while time.time() - start_time < timeout:
        status_data = query_task_status(request_id)
        status = status_data.get("status", "Unknown")
        
        print(f"⏳ 任务状态：{status}")
        
        if status == "Success":
            return status_data
        elif status in ["Failed", "Canceled"]:
            raise Exception(f"任务失败：{status_data}")
        
        time.sleep(poll_interval)
    
    raise Exception(f"任务超时（{timeout}秒）")

def download_file(url, output_path):
    """下载文件"""
    print(f"📥 下载结果：{output_path}")
    
    response = requests.get(url, stream=True, timeout=60)
    if response.status_code != 200:
        raise Exception(f"下载失败：{response.status_code}")
    
    # 确保目录存在
    os.makedirs(os.path.dirname(output_path) or ".", exist_ok=True)
    
    with open(output_path, 'wb') as f:
        for chunk in response.iter_content(chunk_size=8192):
            f.write(chunk)
    
    print(f"✅ 保存成功：{output_path}")

def parse_args():
    """解析命令行参数"""
    parser = argparse.ArgumentParser(description="BizyAir Banana 2 图像生成")
    
    parser.add_argument("-p", "--prompt", required=True, help="提示词")
    parser.add_argument("-i", "--image", required=True, help="输出图片路径")
    parser.add_argument("-r", "--ref", action="append", help="参考图片路径（可多个）")
    parser.add_argument("--web-app-id", type=int, default=47091, help="Web App ID（默认：47091）")
    parser.add_argument("--ar", default="9:16", help="宽高比（默认：9:16）")
    parser.add_argument("--mode", default="third-party", help="模式：third-party|custom")
    parser.add_argument("--resolution", default="1k", help="分辨率：auto, 1k, 2k")
    parser.add_argument("--timeout", type=int, default=120, help="超时时间（秒）")
    parser.add_argument("--json", action="store_true", help="JSON 输出")
    
    return parser.parse_args()

def main():
    global api_key
    args = parse_args()
    
    # 获取 API Key
    [REDACTED_SECRET])
    if not [REDACTED_SECRET]"❌ 错误：未配置 BIZYAIR_API_KEY")
        print("\n请通过以下方式之一配置：")
        print("1. 环境变量：export BIZYAIR_API_KEY=\"your_key\"")
        print("2. 配置文件：在技能目录创建 .env 文件")
        print("   位置：" + os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + "/.env")
        print("\n获取 API Key: https://www.bizyair.cn")
        sys.exit(1)
    
    print("🎨 BizyAir Banana 2 图像生成")
    print("=" * 50)
    print(f"提示词：{args.prompt}")
    print(f"输出：{args.image}")
    print(f"Web App ID: {args.web_app_id}")
    print(f"宽高比：{args.ar}")
    print(f"模式：{args.mode}")
    print("")
    
    try:
        # 准备输入值
        input_values = {
            "10:BizyAir_NanoBanana2.resolution": args.resolution,
            "10:BizyAir_NanoBanana2.aspect_ratio": args.ar,
            "10:BizyAir_NanoBanana2.mode": args.mode,
        }
        
        # 处理参考图
        if args.ref:
            for idx, ref_path in enumerate(args.ref):
                if os.path.exists(ref_path):
                    # 上传参考图
                    file_url = upload_file(ref_path)
                    # 根据序号映射到节点（示例代码中的 2/3/4 节点）
                    node_id = 2 + idx
                    input_values[f"{node_id}:LoadImage.image"] = file_url
                    print(f"✅ 参考图 {idx+1}: {ref_path} -> {file_url}")
                else:
                    print(f"⚠️  参考文件不存在：{ref_path}")
        
        # 添加提示词（节点 9）
        input_values["9:JjkText.text"] = args.prompt
        
        # 分辨率参数转换为大写
        resolution_map = {"1k": "1K", "2k": "2K", "4k": "4K", "auto": "auto"}
        input_values["10:BizyAir_NanoBanana2.resolution"] = resolution_map.get(args.resolution.lower(), "auto")
        
        # 提交任务
        request_id = submit_task(args.web_app_id, input_values, timeout=args.timeout)
        
        # 等待完成（如果是异步任务）
        print("")
        result = wait_for_task(request_id, timeout=args.timeout)
        
        # 获取输出
        outputs = get_task_outputs(request_id)
        
        if not outputs:
            raise Exception("没有生成结果")
        
        # 下载结果
        output_url = outputs[0]["object_url"]
        download_file(output_url, args.image)
        
        # 输出统计
        print("")
        print("✅ 生成完成！")
        cost_times = result.get("cost_times", {})
        if cost_times:
            print(f"📊 总耗时：{cost_times.get('total_cost_time', 'N/A')}ms")
            print(f"📊 推理耗时：{cost_times.get('inference_cost_time', 'N/A')}ms")
        
        if args.json:
            print(json.dumps({
                "success": True,
                "image": args.image,
                "request_id": request_id,
                "outputs": outputs,
                "cost_times": cost_times,
            }, indent=2, ensure_ascii=False))
        
    except Exception as e:
        print("")
        print(f"❌ 生成失败：{e}")
        
        if args.json:
            print(json.dumps({
                "success": False,
                "error": str(e),
            }, indent=2, ensure_ascii=False))
        
        sys.exit(1)

if __name__ == "__main__":
    main()


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