--- name: IMA Studio Image Generation description: "AI image generation with SeeDream 4.5, Midjourney, Nano Banana 2, Nano Banana Pro. Text-to-image, image-to-image with intelligent model selection and knowledge base support. BEFORE using: READ ima-knowledge-ai skill for aesthetics and best practices. Use for: AI art, product photos, character design, logo design, poster creation, social media graphics. Supports 1K/2K/4K resolution. Requires IMA API key." --- # IMA Image AI Creation ## ⚠️ 重要:模型 ID 参考 **CRITICAL:** When calling the script, you MUST use the exact **model_id** (second column), NOT the friendly model name. Do NOT infer model_id from the friendly name. **Quick Reference Table:** | 友好名称 (Friendly Name) | model_id | 说明 (Notes) | |-------------------------|----------|-------------| | Nano Banana2 | `gemini-3.1-flash-image` | ❌ NOT nano-banana-2, 预算选择 4-13 pts | | Nano Banana Pro | `gemini-3-pro-image` | ❌ NOT nano-banana-pro, 高质量 10-18 pts | | SeeDream 4.5 | `doubao-seedream-4.5` | ✅ Recommended default, 5 pts | | Midjourney | `midjourney` | ✅ Same as friendly name, 8-10 pts | **User Input Variations Handled by Agent:** - "香蕉" / "香蕉2" / "小香蕉" → Nano Banana2 → `gemini-3.1-flash-image` - "香蕉Pro" / "香蕉专业版" / "大香蕉" → Nano Banana Pro → `gemini-3-pro-image` - "可梦" / "豆包可梦" / "SeeDream" → `doubao-seedream-4.5` - "MJ" / "Midjourney" → `midjourney` **How to get the correct model_id:** 1. Check this table first 2. Use `--list-models --task-type text_to_image` (or `image_to_image`) 3. Refer to command examples below **Example:** ```bash # ❌ WRONG: Inferring from friendly name --model-id nano-banana-pro # ✅ CORRECT: Using exact model_id from table --model-id gemini-3-pro-image ``` --- ## ⚠️ MANDATORY PRE-CHECK: Read Knowledge Base First! **If ima-knowledge-ai is not installed:** Skip all "Read …" steps below; use only this SKILL's default models and the **📥 User Input Parsing** tables for task_type, model_id, and parameters. **BEFORE executing ANY image generation task, you MUST:** 1. **Check for visual consistency needs** — Read `ima-knowledge-ai/references/visual-consistency.md` if: - User mentions: "系列"、"多张"、"同一个"、"角色"、"续"、"series"、"same" - Task involves: multiple images, character actions, product shots, video stills - Second+ request about same subject (e.g., "旺财在游泳" after "生成旺财照片") 2. **Check workflow/model/parameters** — Read relevant `ima-knowledge-ai/references/` sections if: - Complex multi-step task - Unsure which model to use - Need parameter guidance (resolution, aspect ratio, etc.) **Why this matters:** - AI generation defaults to **独立生成** (independent generation) each time - Without reference images, "same character/product" will look different - **Text-to-image CANNOT maintain visual consistency** — must use image-to-image with reference **Example failure case:** ``` User: "生成一只小狗,叫旺财" → You: generate dog image A User: "生成旺财在游泳的视频" → ❌ Wrong: generate new dog (looks different) → ✅ Right: read visual-consistency.md → use image A as reference ``` **How to check:** ```python # Step 1: Read knowledge base read("~/.openclaw/skills/ima-knowledge-ai/references/visual-consistency.md") # Step 2: Identify if reference image needed if "same subject" or "series" or "character": # Use image-to-image with previous result as reference reference_image = previous_generation_result use_image_to_image(prompt, reference_image, reference_strength=0.8) else: # OK to use text-to-image use_text_to_image(prompt) ``` **No exceptions** — if you skip this check and generate visually inconsistent results, that's a bug. --- ## 📥 User Input Parsing (Model & Parameter Recognition) **Purpose:** So that any agent (Claude or other models) parses user intent consistently, follow these rules when deriving **task_type**, **model_id**, and **parameters** from natural language. Normalize first, then map. ### 1. User phrasing → task_type | User intent / phrasing | task_type | Notes | |------------------------|-----------|--------| | Only text, no input image | `text_to_image` | "画一张…" / "生成图片" / "text to image" | | One input image + edit/transform | `image_to_image` | "把这张图…" / "参考这张图生成" / "图生图" / "风格迁移" | If the user attaches or links one image and asks to change it or generate something "like this" (same subject/style), use `image_to_image` with that image as input. ### 2. Model name / alias → model_id (normalize then lookup) Normalize user wording (case-insensitive), then map to **model_id**: | User says (examples) | model_id | Notes | |----------------------|----------|--------| | 可梦 / SeeDream / 豆包可梦 / Seedream | `doubao-seedream-4.5` | Default, 5 pts | | Midjourney / MJ / Mid journey | `midjourney` | Artistic, 8–10 pts | | Nano Banana / 香蕉 / Banana2 / NB2 | `gemini-3.1-flash-image` | Nano Banana2, 4–13 pts | | Nano Banana Pro / Banana Pro / NB Pro | `gemini-3-pro-image` | Premium, 10–18 pts | | 最便宜 / 最省钱 / cheapest / budget | `gemini-3.1-flash-image` (512px) | 4 pts | | 最好 / 最高质量 / best / premium | `gemini-3-pro-image` (4K) or SeeDream 4.5 | — | | 艺术 / 插画 / artistic / 画风 | `midjourney` | When user wants illustration/art style | If the user names a model not in the table, match by **Name** in the "Supported Models" section below and use its **model_id**. ### 3. User phrasing → size / aspect_ratio | User says (examples) | Parameter | Normalized value | Notes | |----------------------|-----------|------------------|-------| | 16:9 / 横图 / 横向 | aspect_ratio | 16:9 | SeeDream / Nano Banana 支持 | | 9:16 / 竖图 / 竖向 | aspect_ratio | 9:16 | — | | 4:3 / 3:4 | aspect_ratio | 4:3 or 3:4 | — | | 1:1 / 方形 | aspect_ratio | 1:1 | — | | 4K / 4k | size | 4K | Nano Banana Pro/2; Midjourney 仅 1:1 | | 2K / 1K / 512 | size | 2K / 1K / 512px | Via attribute_id for Nano Banana | **Midjourney**: Does not support custom aspect_ratio (fixed 1024×1024). If user asks for 16:9 etc. with "MJ", recommend SeeDream 4.5 or Nano Banana and use their model_id. **8K**: No model supports 8K; max is 4K — inform user and use 4K if they insist on "highest resolution". --- ## 💬 User Experience Protocol (IM / Feishu / Discord) v1.3 🆕 > **CRITICAL FIX in v1.2:** Added Step 0 to ensure correct message ordering in group chats. > **NEW in v1.3:** Added original image URL in Step 3 caption for easy copying/sharing. > > **v1.1 Bug:** Confirmation message ("好的!来帮你画...") appeared LAST because it used `NO_REPLY`. > **v1.2 Fix:** Always reply with confirmation FIRST (Step 0), then push updates via `message` tool. > **v1.3 Enhancement:** Include `🔗 原始链接:[url]` in success caption so users can copy/share the URL. This skill runs inside IM platforms (Feishu, Discord via OpenClaw). **Never let users wait in silence.** Always follow all 6 steps below, every single time. ### 🚫 Never Say to Users | ❌ Never say | ✅ What users care about | |-------------|--------------------------| | `ima_image_create.py` / 脚本 / script | — | | 自动化脚本 / automation | — | | 自动处理产品列表 / 查询接口 | — | | 自动解析参数 / 智能轮询 | — | | attribute_id / model_version / form_config | — | | API 调用 / HTTP 请求 / 任何技术参数名 | — | Only tell users: **model name · estimated time · credits · result (image/media) · plain-language status**. --- ### Estimated Generation Time per Model | Model | Estimated Time | Poll Every | Send Progress Every | |-------|---------------|------------|---------------------| | **SeeDream 4.5** 🌟 | 30~60s | 5s | 20s | | **Nano Banana2** 💚 | 20~40s | 5s | 15s | | **Nano Banana Pro** | 60~120s | 5s | 30s | | **Midjourney** 🎨 | 40~90s | 8s | 25s | `estimated_max_seconds` = the upper bound of the range above (e.g. 60 for SeeDream 4.5, 120 for Nano Banana Pro, 90 for Midjourney). --- ### Step 0 — Initial Acknowledgment Reply (Normal Reply) 🆕 **⚠️ CRITICAL:** This step is NEW in v1.2 and fixes the message ordering bug. **Before doing anything else**, reply to the user with a friendly acknowledgment message using your **normal reply** (not `message` tool). This reply will automatically appear FIRST in the conversation. **Example acknowledgment messages:** ``` 好的!来帮你画一只萌萌的猫咪 🐱 ``` ``` 收到!马上为你生成一张 16:9 的风景照 🏔️ ``` ``` OK! Starting image generation with SeeDream 4.5 🎨 ``` **Rules:** - Keep it short and warm (< 15 words) - Match the user's language (Chinese/English) - Include relevant emoji (🐱/🎨/✨) - This is your ONLY normal reply — all subsequent updates use `message` tool **Why this matters:** - Normal replies automatically appear FIRST in the conversation thread - `message` tool pushes appear in chronological order AFTER your initial reply - This ensures users see: "好的!" → "🎨 开始生成..." → "✅ 成功!" (correct order) --- ### Step 1 — Pre-Generation Notification (Push via message tool) **After Step 0 reply**, use the `message` tool to push a notification immediately to the group/channel: ```python # Agent implementation message( action="send", target=group_id, # or channel_id for Discord message="""🎨 开始生成图片,请稍候… • 模型:[Model Name] • 预计耗时:[X ~ Y 秒] • 消耗积分:[N pts]""" ) ``` **User-facing message template:** ``` 🎨 开始生成图片,请稍候… • 模型:[Model Name] • 预计耗时:[X ~ Y 秒] • 消耗积分:[N pts] ``` **Cost transparency examples:** - Balanced/default (5-6 pts): "使用 SeeDream 4.5(5 积分,性价比最佳)" - Premium (>10 pts): "使用 Nano Banana Pro(10-18 积分,最高质量,支持 1K/2K/4K)" - Budget (user explicit): "使用 Nano Banana2(4 积分,最便宜最快)" > Adapt language to match the user. Chinese → `🎨 开始生成图片,请稍候…` / English → `🎨 Starting image generation, please wait…` --- ### Step 2 — Progress Updates (Push via message tool) **Implementation:** 1. Start the generation script in background or use polling loop 2. Track elapsed time since start 3. Every `[Send Progress Every]` seconds (from table above), push a progress update via `message` tool 4. Stop when task completes (success/failure) **Progress message template:** ``` ⏳ 正在生成中… [P]% 已等待 [elapsed]s,预计最长 [max]s ``` **Progress formula:** ```python P = min(95, floor(elapsed_seconds / estimated_max_seconds * 100)) ``` **Rules:** - **Cap at 95%** — never show 100% until the API returns `success` - If `elapsed > estimated_max`: keep P at 95% and append `「稍等,即将完成…」` - Example: elapsed=40s, max=60s → P = min(95, floor(40/60*100)) = min(95, 66) = **66%** **When to send progress:** - **Short tasks (<20s)**: No progress needed, skip Step 2 - **Medium tasks (20-60s)**: Send 1-2 updates - **Long tasks (>60s)**: Send updates every 20-30s --- ### Step 3 — Success Notification (Push image via message tool) When task status = `success`, use the `message` tool to **send the generated image directly** (not as a text URL): **Agent implementation:** ```python # Get result URL from script output or task detail API result = get_task_result(task_id) image_url = result["medias"][0]["url"] # Build caption caption = f"""✅ 图片生成成功! • 模型:[Model Name] • 耗时:预计 [X~Y]s,实际 [actual]s • 消耗积分:[N pts] 🔗 原始链接:{image_url}""" # Add mismatch hint if user pref conflicts with knowledge-ai recommendation if user_pref_exists and knowledge_recommended_model != used_model: caption += f""" 💡 提示:当前任务也许用 {knowledge_recommended_model} 也会不错({reason},{cost} pts)""" # Push image + caption to group/channel message( action="send", target=group_id, media=image_url, # Feishu/Discord will render the image caption=caption ) ``` **Mismatch hint example:** ``` ✅ 图片生成成功! • 模型:Midjourney(你的偏好模型) • 耗时:45s • 消耗积分:8 pts 🔗 原始链接:https://... 💡 提示:当前任务也许用 SeeDream 4.5 也会不错(写实风格更合适,5 pts) [图片直接显示在上方] ``` **Important:** - Hint is **non-intrusive** — does NOT interrupt generation - Only shown when user pref conflicts with knowledge-ai recommendation - User can ignore the hint; image is already delivered **Platform-specific notes:** - **Feishu**: `message(action=send, media=url, caption="...")` — caption appears below image - **Discord**: Image embeds automatically from URL; caption can be in message text - **Telegram**: Use `message(action=send, media=url, caption="...")` **⚠️ Important**: Do NOT send plain text URL like `https://cdn.../image.jpg`. Users expect to see the actual image rendered. --- ### Step 4 — Failure Notification (Push via message tool) When task status = `failed` or any API/network error, push a failure message with alternative suggestions: **Agent implementation:** ```python message( action="send", target=group_id, message="""❌ 图片生成失败 • 原因:[natural_language_error_message] • 建议改用: - [Alt Model 1]([特点],[N pts]) - [Alt Model 2]([特点],[N pts]) 需要我帮你用其他模型重试吗?""" ) ``` **⚠️ CRITICAL: Error Message Translation** **NEVER show technical error messages to users.** Always translate API errors into natural language. **API key & credits:** 密钥与积分管理入口为 imaclaw.ai(与 imastudio.com 同属 IMA 平台)。Key and subscription management: imaclaw.ai (same IMA platform as imastudio.com). | Technical Error | ❌ Never Say | ✅ Say Instead (Chinese) | ✅ Say Instead (English) | |----------------|-------------|------------------------|------------------------| | `401 Unauthorized` 🆕 | Invalid API key / 401 Unauthorized | ❌ API密钥无效或未授权
💡 **生成新密钥**: https://www.imaclaw.ai/imaclaw/apikey | ❌ API key is invalid or unauthorized
💡 **Generate API Key**: https://www.imaclaw.ai/imaclaw/apikey | | `4008 Insufficient points` 🆕 | Insufficient points / Error 4008 | ❌ 积分不足,无法创建任务
💡 **购买积分**: https://www.imaclaw.ai/imaclaw/subscription | ❌ Insufficient points to create this task
💡 **Buy Credits**: https://www.imaclaw.ai/imaclaw/subscription | | `"Invalid product attribute"` / `"Insufficient points"` | Invalid product attribute | 生成参数配置异常,请稍后重试 | Configuration error, please try again later | | `Error 6006` (credit mismatch) | Error 6006 | 积分计算异常,系统正在修复 | Points calculation error, system is fixing | | `Error 6010` (attribute_id mismatch) | Attribute ID does not match | 模型参数不匹配,请尝试其他模型 | Model parameters incompatible, try another model | | `error 400` (bad request, e.g. invalid size) | error 400 / Bad request | 图片参数设置有误,请调整尺寸或比例 | Image parameter error, adjust size or aspect ratio | | `resource_status == 2` | Resource status 2 / Failed | 图片生成遇到问题,建议换个模型试试 | Image generation failed, try another model | | `status == "failed"` (no details) | Task failed | 这次生成没成功,要不换个模型试试? | Generation unsuccessful, try a different model? | | `timeout` | Task timed out / Timeout error | 生成时间过长已超时,建议用更快的模型 | Generation took too long, try a faster model | | Network error / Connection refused | Connection refused / Network error | 网络连接不稳定,请检查网络后重试 | Network connection unstable, check network and retry | | Rate limit exceeded | 429 Too Many Requests / Rate limit | 请求过于频繁,请稍等片刻再试 | Too many requests, please wait a moment | | Model unavailable | Model not available / 503 Service Unavailable | 当前模型暂时不可用,建议换个模型 | Model temporarily unavailable, try another model | | Unsupported aspect ratio (Nano Banana Pro) | Parameter not supported | 该模型不支持自定义比例,推荐使用 SeeDream 4.5 | This model doesn't support custom aspect ratios, try SeeDream 4.5 | **Generic fallback (when error is unknown):** - Chinese: `图片生成遇到问题,请稍后重试或换个模型试试` - English: `Image generation encountered an issue, please try again or use another model` **Best Practices:** 1. **Focus on user action**: Tell users what to do next, not what went wrong technically 2. **Be reassuring**: Use phrases like "建议换个模型试试" instead of "生成失败了" 3. **Avoid blame**: Never say "你的参数有问题" → say "参数需要调整一下" 4. **Provide alternatives**: Always suggest 1-2 alternative models in the failure message 5. **Image-specific**: For aspect ratio errors, recommend SeeDream 4.5 (supports custom ratios) 6. **🆕 Include actionable links (v1.0.8+)**: For 401/4008 errors, provide clickable links to API key generation or credit purchase pages **🆕 Enhanced Error Handling (v1.0.8):** The Reflection mechanism (3 automatic retries) now provides **specific, actionable suggestions** for common errors: - **401 Unauthorized**: System suggests generating a new API key with clickable link - **4008 Insufficient Points**: System suggests purchasing credits with clickable link - **500 Internal Server Error**: Automatic parameter degradation (size: 4K → 2K → 1K → 512px) - **6009 No Rule Match**: Automatic parameter completion from credit_rules - **6010 Attribute Mismatch**: Automatic credit_rule reselection - **Timeout**: Helpful info with dashboard link for background task status All error handling is **automatic and transparent** — users receive natural language explanations with next steps. **Failure fallback table:** | Failed Model | First Alt | Second Alt | |-------------|-----------|------------| | **SeeDream 4.5** | **Nano Banana2**(4pts,快速便宜) | **Nano Banana Pro**(10-18pts,高质量) | | **Nano Banana2** | **SeeDream 4.5**(5pts,更高质量) | **Nano Banana Pro**(10-18pts) | | **Nano Banana Pro** | **SeeDream 4.5**(5pts,性价比高) | **Nano Banana2**(4pts,最便宜) | | Any / Unknown | **SeeDream 4.5**(5pts,默认首选) | **Nano Banana2**(4pts,预算紧张) | --- ### Step 5 — Done (No Further Action Needed) 🆕 **v1.2 Change:** Step 5 is now simplified. After completing Steps 0-4: - ✅ **Step 0** already sent your normal reply (appears FIRST in chat) - ✅ **Steps 1-4** pushed all updates via `message` tool (appear in order) - ✅ **No further action needed** — conversation is complete **Do NOT:** - ❌ Reply again with `NO_REPLY` (you already replied in Step 0) - ❌ Send duplicate confirmation messages - ❌ Use `message` tool to send the same content twice **Why this works:** ``` User: "帮我画一只猫" ↓ [Step 0] Your normal reply: "好的!来帮你画一只萌萌的猫咪 🐱" ← Appears FIRST ↓ [Step 1] message tool push: "🎨 开始生成图片..." ← Appears SECOND ↓ [Step 2] message tool push: "⏳ 正在生成中… 45%" ← (if task takes >20s) ↓ [Step 3] message tool push: "✅ 图片生成成功! [图片]" ← Appears LAST ↓ [Step 5] Done. No further replies. ``` --- ### 🎯 Summary: What Changed in v1.2 & v1.3 | Version | Step | Change | |---------|------|--------| | **v1.2** | Step 0 | ✅ **NEW:** Normal reply with acknowledgment (appears FIRST) | | **v1.2** | Step 1 | Use `message` tool for **notification only** (not all messages) | | **v1.2** | Step 5 | ✅ **FIXED:** No further action (already replied in Step 0), no `NO_REPLY` | | **v1.3** | Step 3 | ✅ **NEW:** Added `🔗 原始链接:[url]` in caption for easy copying | **Root cause of v1.1 bug:** - v1.1 used `message` tool for ALL messages (including acknowledgment) - Then replied `NO_REPLY` to suppress normal reply - Result: Acknowledgment appeared LAST (because `message` tool pushes are chronological) **v1.2 fix:** - Step 0 uses normal reply (automatically appears FIRST) - Steps 1-4 use `message` tool (appear in chronological order) - No `NO_REPLY` needed (already replied in Step 0) **v1.3 enhancement:** - Step 3 caption now includes original image URL - Users can easily copy/share the link without asking --- ## Complete Example: Correct v1.2 Flow ```python # User: "帮我画一只可爱的猫咪" # Step 0: Normal reply (appears FIRST in chat) # Agent's normal response mechanism automatically handles this reply_text = "好的!来帮你画一只萌萌的猫咪 🐱" # (This is your normal LLM response, not a tool call) # Step 1: Push start notification message( action="send", target="oc_b30b266d43b69674e3ad160de9d13cf2", message="🎨 开始生成图片,请稍候…\n• 模型:SeeDream 4.5\n• 预计耗时:30~60秒\n• 消耗积分:5 pts" ) # Background: Start generation exec(command="python3 ima_image_create.py ...", background=True, sessionId=sid) # Step 2: Progress updates (if task takes >20s) # (Poll in background and push updates via message tool) start_time = time.time() while not done: elapsed = int(time.time() - start_time) if elapsed >= 20 and elapsed % 20 == 0: # Every 20s progress = min(95, int(elapsed / 60 * 100)) message( action="send", target="oc_b30b266d43b69674e3ad160de9d13cf2", message=f"⏳ 正在生成中… {progress}%\n已等待 {elapsed}s,预计最长 60s" ) time.sleep(5) # Poll every 5s # Step 3: Success (push image) result = get_result(task_id) message( action="send", target="oc_b30b266d43b69674e3ad160de9d13cf2", media="https://ws.esxscloud.com/.../image.jpeg", caption=f"✅ 图片生成成功!\n• 模型:SeeDream 4.5\n• 耗时:实际 35s\n• 消耗积分:5 pts\n\n🔗 原始链接:{result['url']}" ) # Step 5: Done — no further action # (Do NOT reply again, do NOT use NO_REPLY) ``` **Result in chat (correct order):** ``` [User] 帮我画一只可爱的猫咪 [Agent] 好的!来帮你画一只萌萌的猫咪 🐱 ← Step 0 (normal reply) [Agent] 🎨 开始生成图片,请稍候… ← Step 1 (message tool) • 模型:SeeDream 4.5 • 预计耗时:30~60秒 • 消耗积分:5 pts [Agent] ⏳ 正在生成中… 66% ← Step 2 (message tool, if >20s) 已等待 40s,预计最长 60s [Agent] ✅ 图片生成成功! ← Step 3 (message tool) • 模型:SeeDream 4.5 • 耗时:实际 35s • 消耗积分:5 pts 🔗 原始链接:https://... [图片] ``` --- ## ⚙️ How This Skill Works **For transparency:** This skill uses a bundled Python script (`scripts/ima_image_create.py`) to call the IMA Open API. The script: - Sends your prompt to IMA's servers (two domains, see below) - Uses `--user-id` **only locally** as a key for storing your model preferences - Returns an image URL when generation is complete ### 🌐 Network Endpoints Used This skill connects to **two domains** owned by IMA Studio for complete functionality: | Domain | Purpose | What's Sent | Authentication | |--------|---------|-------------|----------------| | `api.imastudio.com` | Main API (task creation, status polling) | Prompts, model params, task IDs | Bearer token (IMA API key) | | `imapi.liveme.com` | Image upload service (OSS token generation) | Image files (for i2i tasks), IMA API key | IMA API key + APP_KEY signature | **Why two domains?** - `api.imastudio.com`: IMA's image generation API (handles task orchestration) - `imapi.liveme.com`: IMA's media storage infrastructure (handles large file uploads) - Both services are **owned and operated by IMA Studio** **Privacy implications:** - Your IMA API key is sent to **both domains** for authentication - Image files are uploaded to `imapi.liveme.com` to obtain CDN URLs (for image_to_image tasks) - Image generation happens on `api.imastudio.com` using the CDN URLs - For text_to_image tasks (no image input), only `api.imastudio.com` is contacted **Security verification:** ```bash # List all network endpoints in the code: grep -n "https://" scripts/ima_image_create.py # Expected output: # 60: DEFAULT_BASE_URL = "https://api.imastudio.com" # 61: DEFAULT_IM_BASE_URL = "https://imapi.liveme.com" ``` **If you're concerned about the two-domain architecture:** 1. Review IMA Studio's privacy policy at https://imastudio.com/privacy 2. Contact IMA technical support to confirm domain ownership: support@imastudio.com 3. Use a test/scoped API key first (see security notice below) ### ⚠️ Credential Security Notice **Your IMA API key is sent to TWO domains:** 1. `api.imastudio.com` — Main image generation API 2. `imapi.liveme.com` — Image upload service (only when using image_to_image tasks) **Both domains are owned by IMA Studio**, but if you're concerned about credential exposure: ✅ **Best practices:** - Use a **test/scoped API key** for initial testing (create at https://imastudio.com/api-keys) - Set a low quota (e.g., 100 credits) for the test key - Rotate your key after testing if needed - Contact IMA support to confirm domain ownership: support@imastudio.com ❌ **Do NOT:** - Use a production key if you're uncomfortable with the two-domain architecture - Share your API key with others - Commit your API key to version control **What gets sent to IMA servers:** - ✅ Your image prompt/description - ✅ Model selection (SeeDream/Nano Banana/Midjourney) - ✅ Image parameters (size, quality, aspect ratio, etc.) - ✅ Image files (for image_to_image tasks, uploaded to `imapi.liveme.com`) - ✅ IMA API key (for authentication to both domains) - ❌ NO user_id (it's only used locally) **What's stored locally:** - `~/.openclaw/memory/ima_prefs.json` - Your model preferences (< 1 KB) - `~/.openclaw/logs/ima_skills/` - Generation logs (auto-deleted after 7 days) ### Agent Execution (Internal Reference) > **Note for users:** You can review the script source at `scripts/ima_image_create.py` anytime. > The agent uses this script to simplify API calls. Network requests go to two IMA Studio domains: `api.imastudio.com` (API) and `imapi.liveme.com` (image uploads for i2i tasks). Use the bundled script internally to ensure correct parameter construction: ```bash # List available models python3 {baseDir}/scripts/ima_image_create.py \ --api-key $IMA_API_KEY \ --task-type text_to_image \ --list-models # Generate image python3 {baseDir}/scripts/ima_image_create.py \ --api-key $IMA_API_KEY \ --task-type text_to_image \ --model-id doubao-seedream-4.5 \ --prompt "a cute puppy running on grass" \ --user-id {user_id} \ --output-json # Image to image python3 {baseDir}/scripts/ima_image_create.py \ --api-key $IMA_API_KEY \ --task-type image_to_image \ --model-id doubao-seedream-4.5 \ --prompt "turn into oil painting style" \ --input-images https://example.com/photo.jpg \ --user-id {user_id} \ --output-json ``` **✅ Local images:** `--input-images` accepts both HTTPS URLs and **local file paths**. Local files are automatically uploaded to IMA CDN by the script (no need to host them first). The script outputs JSON — parse it to get the result URL and pass it to the user via the UX protocol messages above. --- ## Overview Call IMA Open API to create AI-generated images. All endpoints require an `ima_*` API key. The core flow is: **query products → create task → poll until done**. --- ## 🔒 Security & Transparency Policy > **This skill is community-maintained and open for inspection.** ### ✅ What Users CAN Do **Full transparency:** - ✅ **Review all source code**: Check `scripts/ima_image_create.py` and `ima_logger.py` anytime - ✅ **Verify network calls**: Network requests go to two IMA Studio domains: `api.imastudio.com` (API) and `imapi.liveme.com` (image uploads for i2i tasks). See "🌐 Network Endpoints Used" section above for full details. - ✅ **Inspect local data**: View `~/.openclaw/memory/ima_prefs.json` and log files - ✅ **Control privacy**: Delete preferences/logs anytime, or disable file writes (see below) **Configuration allowed:** - ✅ **Set API key** in environment or agent config: - Environment variable: `export IMA_API_KEY=ima_your_key_here` - OpenClaw/MCP config: Add `IMA_API_KEY` to agent's environment configuration - Get your key at: https://imastudio.com - ✅ **Use scoped/test keys**: Test with limited API keys, rotate after testing - ✅ **Disable file writes**: Make prefs/logs read-only or symlink to `/dev/null` **Data control:** - ✅ **View stored data**: `cat ~/.openclaw/memory/ima_prefs.json` - ✅ **Delete preferences**: `rm ~/.openclaw/memory/ima_prefs.json` (resets to defaults) - ✅ **Delete logs**: `rm -rf ~/.openclaw/logs/ima_skills/` (auto-cleanup after 7 days anyway) ### ⚠️ Advanced Users: Fork & Modify If you need to modify this skill for your use case: 1. **Fork the repository** (don't modify the original) 2. **Update your fork** with your changes 3. **Test thoroughly** with limited API keys 4. **Document your changes** for troubleshooting **Note:** Modified skills may break API compatibility or introduce security issues. Official support only covers the unmodified version. ### ❌ What to AVOID (Security Risks) **Actions that could compromise security:** - ❌ Sharing API keys publicly or in skill files - ❌ Modifying API endpoints to unknown servers - ❌ Disabling SSL/TLS certificate verification - ❌ Logging sensitive user data (prompts, IDs, etc.) - ❌ Bypassing authentication or billing mechanisms **Why this matters:** 1. **API Compatibility**: Skill logic aligns with IMA Open API schema 2. **Security**: Malicious modifications could leak credentials or bypass billing 3. **Support**: Modified skills may not be supported 4. **Community**: Breaking changes affect all users ### 📋 Privacy & Data Handling Summary **What this skill does with your data:** | Data Type | Sent to IMA? | Stored Locally? | User Control | |-----------|-------------|-----------------|--------------| | Image prompts | ✅ Yes (required for generation) | ❌ No | None (required) | | API key | ✅ Yes (authentication header) | ❌ No | Set via env var | | user_id (optional CLI arg) | ❌ **Never** (local preference key only) | ✅ Yes (as prefs file key) | Change `--user-id` value | | Model preferences | ❌ No | ✅ Yes (~/.openclaw) | Delete anytime | | Generation logs | ❌ No | ✅ Yes (~/.openclaw) | Auto-cleanup 7 days | **Privacy recommendations:** 1. **Use test/scoped API keys** for initial testing 2. **Note**: `--user-id` is **never sent to IMA servers** - it's only used locally as a key for storing preferences in `~/.openclaw/memory/ima_prefs.json` 3. **Review source code** at `scripts/ima_image_create.py` to verify network calls (search for `create_task` function) 4. **Rotate API keys** after testing or if compromised **Get your IMA API key:** Visit https://imastudio.com to register and get started. ### 🔧 For Skill Maintainers Only **Version control:** - All changes must go through Git with proper version bumps (semver) - CHANGELOG.md must document all changes - Production deployments require code review **File checksums (optional):** ```bash # Verify skill integrity sha256sum SKILL.md scripts/ima_image_create.py ``` If users report issues, verify file integrity first. --- ## 🧠 User Preference Memory > User preferences have **highest priority** when they exist. But preferences are only saved when users **explicitly express** model preferences — not from automatic model selection. ### Storage: `~/.openclaw/memory/ima_prefs.json` ```json { "user_{user_id}": { "text_to_image": { "model_id": "doubao-seedream-4.5", "model_name": "SeeDream 4.5", "credit": 5, "last_used": "2026-02-26T03:07:27Z" }, "image_to_image": { "model_id": "doubao-seedream-4.5", "model_name": "SeeDream 4.5", "credit": 5, "last_used": "2026-02-25T10:00:00Z" } } } ``` ### Model Selection Flow (Every Generation) **Step 1: Get knowledge-ai recommendation** (if installed) ```python knowledge_recommended_model = read_ima_knowledge_ai() # e.g., "SeeDream 4.5" ``` **Step 2: Check user preference** ```python user_pref = load_prefs().get(f"user_{user_id}", {}).get(task_type) # e.g., {"model_id": "midjourney", ...} ``` **Step 3: Decide which model to use** ```python if user_pref exists: use_model = user_pref["model_id"] # Highest priority else: use_model = knowledge_recommended_model or fallback_default ``` **Step 4: Check for mismatch (for later hint)** ```python if user_pref exists and knowledge_recommended_model != user_pref["model_id"]: mismatch = True # Will add hint in success message ``` ### When to Write (User Explicit Preference ONLY) **✅ Save preference when user explicitly specifies a model:** | User says | Action | |-----------|--------| | `用XXX` / `换成XXX` / `改用XXX` | Switch to model XXX + save as preference | | `以后都用XXX` / `默认用XXX` / `always use XXX` | Save + confirm: `✅ 已记住!以后图片生成默认用 [XXX]` | | `我喜欢XXX` / `我更喜欢XXX` | Save as preference | **❌ Do NOT save when:** - Agent auto-selects from knowledge-ai → not user preference - Agent uses fallback default → not user preference - User says generic quality requests (see "Clear Preference" below) → clear preference instead ### When to Clear (User Abandons Preference) **🗑️ Clear preference when user wants automatic selection:** | User says | Action | |-----------|--------| | `用最好的` / `用最合适的` / `best` / `recommended` | Clear pref + use knowledge-ai recommendation | | `推荐一个` / `你选一个` / `自动选择` | Clear pref + use knowledge-ai recommendation | | `用默认的` / `用新的` | Clear pref + use knowledge-ai recommendation | | `试试别的` / `换个试试` (without specific model) | Clear pref + use knowledge-ai recommendation | | `重新推荐` | Clear pref + use knowledge-ai recommendation | **Implementation:** ```python del prefs[f"user_{user_id}"][task_type] save_prefs(prefs) ``` --- ## ⭐ Model Selection Priority **Selection flow:** 1. **User preference** (if exists) → Highest priority, always respect 2. **ima-knowledge-ai skill** (if installed) → Professional recommendation based on task 3. **Fallback defaults** → Use table below (only if neither 1 nor 2 exists) **Important notes:** - User preference is only saved when user **explicitly specifies** a model (see "When to Write" above) - Knowledge-ai is **always consulted** (even when user pref exists) to detect mismatches - When mismatch detected → add gentle hint in success message (does NOT interrupt generation) > The defaults below are FALLBACK only. User preferences have highest priority, then knowledge-ai recommendations. > **Always default to the newest and most popular model. Do NOT default to the cheapest.** | Task | Default Model | model_id | version_id | Cost | Why | |------|--------------|----------|------------|------|-----| | text_to_image | **SeeDream 4.5** | `doubao-seedream-4.5` | `doubao-seedream-4-5-251128` | 5 pts | Latest doubao flagship, photorealistic 4K | | text_to_image (budget) | **Nano Banana2** | `gemini-3.1-flash-image` | `gemini-3.1-flash-image` | 4 pts | Fastest and cheapest option | | text_to_image (premium) | **Nano Banana Pro** | `gemini-3-pro-image` | `gemini-3-pro-image-preview` | 10/10/18 pts | Premium quality, 1K/2K/4K options | | text_to_image (artistic) | **Midjourney** 🎨 | `midjourney` | `v6` | 8/10 pts | Artist-level aesthetics, creative styles | | image_to_image | **SeeDream 4.5** | `doubao-seedream-4.5` | `doubao-seedream-4-5-251128` | 5 pts | Latest, best i2i quality | | image_to_image (budget) | **Nano Banana2** | `gemini-3.1-flash-image` | `gemini-3.1-flash-image` | 4 pts | Cheapest option | | image_to_image (premium) | **Nano Banana Pro** | `gemini-3-pro-image` | `gemini-3-pro-image-preview` | 10 pts | Premium quality | | image_to_image (artistic) | **Midjourney** 🎨 | `midjourney` | `v6` | 8/10 pts | Artist-level aesthetics, style transfer | **Selection guide by use case:** - General image generation → **SeeDream 4.5** (5pts) - **Custom aspect ratio (16:9, 9:16, 4:3, etc.)** → **SeeDream 4.5** 🌟 or **Nano Banana Pro/2/MAX** 🆕 (native support) - Budget-conscious / fast generation → **Nano Banana2** (4pts) - Highest quality with size control (1K/2K/4K) → **Nano Banana Pro** (text_to_image: 10-18pts, image_to_image: 10pts) - **Artistic/creative styles, illustrations, paintings** → **Midjourney** 🎨 (8-10pts) - Style transfer / image editing → **SeeDream 4.5** (5pts) or **Midjourney** 🎨 (artistic) **🆕 MAJOR UPDATE: Nano Banana series now has NATIVE aspect_ratio support!** - **Nano Banana Pro**: ✅ Supports `aspect_ratio` (1:1, 16:9, 9:16, 4:3, 3:4) NATIVELY - **Nano Banana2**: ✅ Supports `aspect_ratio` (1:1, 16:9, 9:16, 4:3, 3:4) NATIVELY - **Nano Banana MAX**: ✅ Supports `aspect_ratio` (1:1, 16:9, 9:16, 4:3, 3:4) NATIVELY **When user requests unsupported combinations:** - **Midjourney + aspect_ratio (16:9, etc.)**: Recommend **SeeDream 4.5** or **Nano Banana series** instead ``` ❌ Midjourney 暂不支持自定义 aspect_ratio(仅支持 1024x1024 方形) ✅ 推荐方案: 1. SeeDream 4.5(支持虚拟参数 aspect_ratio) 2. Nano Banana Pro/2/MAX(原生支持 aspect_ratio) • 支持比例:1:1, 16:9, 9:16, 4:3, 3:4 ``` • 成本:5 积分(性价比最佳) • 质量:4K photorealistic 需要我帮你用 SeeDream 4.5 生成吗? ``` - **Any model + 8K**: Inform user no model supports 8K, max is 4K (Nano Banana Pro or SeeDream 4.5) - **Any model + 7:3 ratio**: Non-standard ratio, not supported. Suggest closest supported ratio (e.g., 21:9 for ultra-wide, 2:3 for portrait) --- ## Supported Models ⚠️ **Production Environment**: **4 image models** are currently available in production (as of 2026-02-28). ### text_to_image (4 models) | Name | model_id | version_id | Cost | attribute_id | Size Options | |------|----------|------------|------|--------------|--------------| | **SeeDream 4.5** 🌟 | `doubao-seedream-4.5` | `doubao-seedream-4-5-251128` | 5 pts | 2341 | Default (adaptive 4k) | | **Nano Banana2** 💚 | `gemini-3.1-flash-image` | `gemini-3.1-flash-image-preview` | 4/6/10/13 pts | 4400/4401/4402/4403 | 512px (4pts) / 1K (6pts) / 2K (10pts) / 4K (13pts) | | **Nano Banana Pro** | `gemini-3-pro-image` | `gemini-3-pro-image-preview` | 10/10/18 pts | 2399/2400/2401 | 1K (10pts) / 2K (10pts) / 4K (18pts) | | **Midjourney** 🎨 | `midjourney` | `v6` | 8/10 pts | 5451/5452 | 480p (8pts) / 720p (10pts) | ### image_to_image (4 models) | Name | model_id | version_id | Cost | attribute_id | Size Options | |------|----------|------------|------|--------------|--------------| | **SeeDream 4.5** 🌟 | `doubao-seedream-4.5` | `doubao-seedream-4-5-251128` | 5 pts | 1611 | Default (adaptive 4k) | | **Nano Banana2** 💚 | `gemini-3.1-flash-image` | `gemini-3.1-flash-image-preview` | 4/6/10/13 pts | 4404/4405/4406/4407 | 512px (4pts) / 1K (6pts) / 2K (10pts) / 4K (13pts) | | **Nano Banana Pro** | `gemini-3-pro-image` | `gemini-3-pro-image-preview` | 10 pts | 2402/2403/2404 | 1K (10pts) / 2K (10pts) / 4K (18pts) | | **Midjourney** 🎨 | `midjourney` | `v6` | 8/10 pts | 5453/5454 | 480p (8pts) / 720p (10pts) | ### Recommended Defaults (Based on Production Data) | Task Type | Default Model | Reason | Cost | |-----------|---------------|--------|------| | **text_to_image** | SeeDream 4.5 | Latest DouBao flagship, balanced quality/cost | 5 pts | | **text_to_image (budget)** | Nano Banana2 | Fastest and cheapest option | 4 pts | | **text_to_image (artistic)** | Midjourney 🎨 | Artist-level aesthetics, creative styles | 8-10 pts | | **image_to_image** | SeeDream 4.5 | Newest, most stable, cost-effective | 5 pts (attribute_id: 1611) | | **image_to_image (budget)** | Nano Banana2 | Cheapest option | 4 pts | | **image_to_image (artistic)** | Midjourney 🎨 | Artist-level aesthetics, style transfer | 8-10 pts | **Premium option**: Nano Banana Pro — Highest quality with size control (1K/2K/4K), higher cost (10-18 pts for text_to_image, 10 pts for image_to_image). ### Model Capabilities (Parameter Support) ⚠️ **Critical**: Models have **varying parameter support**. Custom aspect ratios are now **supported by multiple models**. | Model | Custom Aspect Ratio | Max Resolution | Size Options | Notes | |-------|---------------------|----------------|--------------|-------| | **SeeDream 4.5** | ✅ (via virtual params) | 4K (adaptive) | 8 aspect ratios | Supports 1:1, 16:9, 9:16, 4:3, 3:4, 2:3, 3:2, 21:9 (5 pts) | | **Nano Banana2** | ✅ **Native support** 🆕 | 4K (4096×4096) | 512px/1K/2K/4K + aspect ratios | Supports 1:1, 16:9, 9:16, 4:3, 3:4; size via `attribute_id` | | **Nano Banana Pro** | ✅ **Native support** 🆕 | 4K (4096×4096) | 1K/2K/4K + aspect ratios | Supports 1:1, 16:9, 9:16, 4:3, 3:4; size via `attribute_id` | | **Midjourney** 🎨 | ❌ (1:1 only) | 1024px (square) | 480p/720p via `attribute_id` | Fixed 1024x1024, artistic style focus | **Key Capabilities**: - ✅ **Aspect ratio control**: **SeeDream 4.5** (virtual params), **Nano Banana Pro/2/MAX** (native support) - ❌ **8K**: Not supported by any model (max is 4K) - ✅ **Size control**: **Nano Banana2**, **Nano Banana Pro**, and **Midjourney** support multiple size options via different `attribute_id`s - ✅ **Budget option**: **Nano Banana2** is the cheapest at 4 pts for 512px, but 4K costs 13pts - 🎨 **Artistic styles**: **Midjourney** excels at creative, artistic, and illustration styles - 💡 **Best value**: **SeeDream 4.5** at 5pts offers aspect ratio flexibility; **Nano Banana2** 512px at 4pts for fastest/cheapest --- ## Environment Base URL: `https://api.imastudio.com` Required/recommended headers for all `/open/v1/` endpoints: | Header | Required | Value | Notes | |--------|----------|-------|-------| | `Authorization` | ✅ | `Bearer ima_your_api_key_here` | API key authentication | | `x-app-source` | ✅ | `ima_skills` | Fixed value — identifies skill-originated requests | | `x_app_language` | recommended | `en` / `zh` | Product label language; defaults to `en` if omitted | ``` Authorization: Bearer ima_your_api_key_here x-app-source: ima_skills x_app_language: en ``` --- ## ⚠️ MANDATORY: Always Query Product List First > **CRITICAL**: You MUST call `/open/v1/product/list` BEFORE creating any task. > The `attribute_id` field is REQUIRED in the create request. If it is `0` or missing, you get: > `"Invalid product attribute"` → `"Insufficient points"` → task fails completely. > **NEVER construct a create request from the model table alone. Always fetch the product first.** ### Why attribute_id is required The `attribute_id` uniquely identifies the exact product variant (model + quality tier). The billing and routing system uses it to: 1. Validate the product is purchasable 2. Deduct the correct credits via `credit_rules` 3. Route the request to the right backend model ### How to get attribute_id ```python # Step 1: Query product list for the target category GET /open/v1/product/list?app=ima&platform=web&category=text_to_image # Step 2: Walk the V2 tree to find your model (type=3 leaf nodes only) for group in response["data"]: for version in group.get("children", []): if version["type"] == "3" and version["model_id"] == target_model_id: attribute_id = version["credit_rules"][0]["attribute_id"] credit = version["credit_rules"][0]["points"] model_version = version["id"] # = version_id model_name = version["name"] form_defaults = {f["field"]: f["value"] for f in version["form_config"]} ``` ### Quick Reference: Known attribute_ids ⚠️ **Production warning**: `attribute_id` and `credit` values change frequently. Always call `/open/v1/product/list` at runtime; table below is pre-queried reference (2026-02-27). **text_to_image**: | Model | model_id | attribute_id | credit | Size | |-------|----------|-------------|--------|------| | **SeeDream 4.5** 🌟 | `doubao-seedream-4.5` | **2341** | 5 pts | Default (adaptive 4k) | | **Nano Banana2** (512px) | `gemini-3.1-flash-image` | **4400** | 4 pts | 512px (512×512) | | **Nano Banana2** (1K) | `gemini-3.1-flash-image` | **4401** | 6 pts | 1K (1024×1024) | | **Nano Banana2** (2K) | `gemini-3.1-flash-image` | **4402** | 10 pts | 2K (2048×2048) | | **Nano Banana2** (4K) | `gemini-3.1-flash-image` | **4403** | 13 pts | 4K (4096×4096) | | Nano Banana Pro (1K) | `gemini-3-pro-image` | **2399** | 10 pts | 1K (1024×1024) | | Nano Banana Pro (2K) | `gemini-3-pro-image` | **2400** | 10 pts | 2K (2048×2048) | | Nano Banana Pro (4K) | `gemini-3-pro-image` | **2401** | 18 pts | 4K (4096×4096) | **image_to_image**: | Model | model_id | attribute_id | credit | Size | |-------|----------|-------------|--------|------| | **SeeDream 4.5** 🌟 | `doubao-seedream-4.5` | **1611** | 5 pts | Default (adaptive 4k) | | **Nano Banana2** (512px) | `gemini-3.1-flash-image` | **4404** | 4 pts | 512px (512×512) | | **Nano Banana2** (1K) | `gemini-3.1-flash-image` | **4405** | 6 pts | 1K (1024×1024) | | **Nano Banana2** (2K) | `gemini-3.1-flash-image` | **4406** | 10 pts | 2K (2048×2048) | | **Nano Banana2** (4K) | `gemini-3.1-flash-image` | **4407** | 13 pts | 4K (4096×4096) | | Nano Banana Pro (1K) | `gemini-3-pro-image` | **2402** | 10 pts | 1K (1024×1024) | | Nano Banana Pro (2K) | `gemini-3-pro-image` | **2403** | 10 pts | 2K (2048×2048) | | Nano Banana Pro (4K) | `gemini-3-pro-image` | **2404** | 10 pts | 4K (4096×4096) | ⚠️ **Note**: Production has 3 models (SeeDream 4.5 + Nano Banana2 + Nano Banana Pro). All other models mentioned in older documentation are no longer available. --- ## Core Flow ``` 1. GET /open/v1/product/list?app=ima&platform=web&category= → REQUIRED: Get attribute_id, credit, model_version, form_config defaults [image_to_image only] 2. Upload input image → get public HTTPS URL → See "Image Upload" section below 3. POST /open/v1/tasks/create → Must include: attribute_id, model_name, model_version, credit, cast, prompt (nested!) 4. POST /open/v1/tasks/detail {task_id: "..."} → Poll every 2–5s until medias[].resource_status == 1 → Extract url from completed media ``` ### Common Mistakes (and resulting errors) | Mistake | Error | |---------|-------| | `attribute_id` is 0 or missing | `"Invalid product attribute"` → Insufficient points | | `attribute_id` outdated (production changed) | Same errors; always query product list first | | `prompt` at outer level instead of `parameters.parameters.prompt` | Prompt ignored or error | | `cast` missing from inner `parameters` | Billing validation failure | | `credit` wrong / missing | Error 6006 | | `model_name` or `model_version` missing | Wrong model routing | | Skip product list, use hardcoded values | All of the above | --- ## Image Upload (Required for image_to_image) **The IMA Open API does NOT accept raw bytes or base64 images. All input images must be public HTTPS URLs.** **Script behavior:** `--input-images` accepts **both URLs and local file paths**. When you pass a local path, the script automatically uploads the file to IMA CDN (imapi.liveme.com) and uses the returned URL — no separate upload step needed when calling the script. When a user provides an image (local file, bytes, base64) and you invoke the script with a path or URL, the script handles upload for local paths. If you have bytes/base64, upload first using the IMA presigned URL flow below (or write to a temp file and pass that path). ### Two-Step Upload Flow ``` Step 1: GET /api/rest/oss/getuploadtoken → { ful, fdl } Step 2: PUT {ful} with raw image bytes → use fdl (CDN URL) as input_images value ``` See `ima-all-ai/SKILL.md` → "Image Upload" section for the complete implementation. ### Quick Reference ```python # If user provides a URL already → use directly if source.startswith("https://"): input_url = source # If user provides a local file → upload first else: token = get_upload_token(uid, ima_token, suffix="jpeg", content_type="image/jpeg", ...) upload_image_to_oss(image_bytes, "image/jpeg", token["ful"]) input_url = token["fdl"] # CDN URL → use as input_images # Then create task task_id = create_task("image_to_image", prompt, product, input_images=[input_url], size="4k") ``` > **CDN**: `https://ima-ga.esxscloud.com/` | **OSS**: `zhubite-imagent-bot.oss-us-east-1.aliyuncs.com` --- ## Supported Task Types | category | Capability | Input | |----------|------------|-------| | `text_to_image` | Text → Image | prompt | | `image_to_image` | Image → Image | prompt + input image URL | --- ## Detail API status values | Field | Type | Values | |-------|------|--------| | **`resource_status`** | int or `null` | `0`=处理中, `1`=可用, `2`=失败, `3`=已删除;`null` 当作 0 | | **`status`** | string | `"pending"`, `"processing"`, `"success"`, `"failed"` | | `resource_status` | `status` | Action | |-------------------|----------|--------| | `0` or `null` | `pending` / `processing` | Keep polling | | `1` | `success` (or `completed`) | Stop when **all** medias are 1; read `url` | | `1` | `failed` | Stop, handle error | | `2` / `3` | any | Stop, handle error | > **Important**: Treat `resource_status: null` as 0. Stop only when **all** medias have `resource_status == 1`. Check `status != "failed"` when rs=1. --- ## API 1: Product List ``` GET /open/v1/product/list?app=ima&platform=web&category=text_to_image ``` Returns a **V2 tree structure**: `type=2` nodes are model groups, `type=3` nodes are versions (leaves). Only `type=3` nodes contain `credit_rules` and `form_config`. ```json [ { "id": "SeeDream", "type": "2", "name": "SeeDream", "model_id": "", "children": [ { "id": "doubao-seedream-4-5-251128", "type": "3", "name": "SeeDream 4.5", "model_id": "doubao-seedream-4.5", "credit_rules": [ { "attribute_id": 2341, "points": 5, "attributes": { "default": "enabled" } } ], "form_config": [ { "field": "size", "type": "tags", "value": "4k", "options": [{"label":"2K","value":"2k"}, {"label":"4K","value":"4k"}] } ] } ] } ] ``` **How to pick a version for task creation:** 1. Traverse nodes to find `type=3` leaves (versions) 2. Use `model_id` and `id` (= `model_version`) from the leaf 3. Pick `credit_rules[].attribute_id` matching your desired quality/size 4. Use `form_config[].value` as default `parameters` values --- ## API 2: Create Task ``` POST /open/v1/tasks/create ``` ### text_to_image — Verified ✅ No image input. `src_img_url: []`, `input_images: []`. ```json { "task_type": "text_to_image", "enable_multi_model": false, "src_img_url": [], "parameters": [{ "attribute_id": 2341, "model_id": "doubao-seedream-4.5", "model_name": "SeeDream 4.5", "model_version": "doubao-seedream-4-5-251128", "app": "ima", "platform": "web", "category": "text_to_image", "credit": 5, "parameters": { "prompt": "a beautiful mountain sunset, photorealistic", "size": "4k", "n": 1, "input_images": [], "cast": {"points": 5, "attribute_id": 2341} } }] } ``` ### image_to_image — Verified ✅ ```json { "task_type": "image_to_image", "enable_multi_model": false, "src_img_url": ["https://example.com/input.jpg"], "parameters": [{ "attribute_id": 1611, "model_id": "doubao-seedream-4.5", "model_name": "SeeDream 4.5", "model_version": "doubao-seedream-4-5-251128", "app": "ima", "platform": "web", "category": "image_to_image", "credit": 5, "parameters": { "prompt": "turn into oil painting style", "size": "4k", "n": 1, "input_images": ["https://example.com/input.jpg","https://example.com/input.jpg"], "cast": {"points": 5, "attribute_id": 1611} } }] } ``` > ⚠️ `size` must be from `form_config` options (e.g. `"2k"`, `"4k"`, `"2048x2048"`). `"adaptive"` is NOT valid for SeeDream 4.5 — causes error 400. > Top-level `src_img_url` **and** `parameters.input_images` must both contain the input image URL. **Key fields**: | Field | Required | Description | |-------|----------|-------------| | `parameters[].credit` | ✅ | Must equal `credit_rules[].points`. Error 6006 if wrong. | | `parameters[].parameters.prompt` | ✅ | Prompt must be nested here, NOT at top level. | | `parameters[].parameters.cast` | ✅ | `{"points": N, "attribute_id": N}` — mirror of credit. | | `parameters[].parameters.n` | ✅ | Number of outputs (usually `1`). | | `parameters[].parameters.input_images` | image_to_image | Array of input image URLs. | | top-level `src_img_url` | image_to_image | Must also contain the input image URL. | Response: `data.id` = task ID for polling. --- ## API 3: Task Detail (Poll) ``` POST /open/v1/tasks/detail {"task_id": ""} ``` Poll every 2–5s. Completed response: ```json { "id": "task_abc", "medias": [{ "resource_status": 1, "url": "https://cdn.../output.jpg", "format": "jpg", "width": 1024, "height": 1024 }] } ``` Output fields: `url`, `width`, `height`, `format` (jpg/png). --- ## FAQ: Parameter Support & Limitations ### Q1: Can I generate 16:9 or 7:3 aspect ratio images? **A:** ✅ **YES! Multiple models now support custom aspect ratios.** **✅ Supported aspect ratios:** - **SeeDream 4.5**: 1:1, 16:9, 9:16, 4:3, 3:4, 2:3, 3:2, 21:9 (via virtual params) - **Nano Banana Pro/2/MAX**: 1:1, 16:9, 9:16, 4:3, 3:4 (native support) 🆕 **❌ Not supported:** - **Midjourney**: Fixed 1024×1024 (1:1 only) - **Custom ratios**: 7:3, 8:3, or other non-standard ratios are NOT supported by any model **Workarounds for unsupported ratios:** 1. **Use video models** (recommended): Generate with video models (e.g., Wan 2.6 text_to_video) that support 16:9, 9:16, 1:1, then extract the first frame as an image. 2. **Post-processing**: Generate a 1:1 image, then crop/extend to desired aspect ratio. **Model recommendation by aspect ratio need:** - **Standard ratios (16:9, 9:16, 4:3, 3:4)**: Nano Banana Pro/2 (native support, no virtual params) - **Extended ratios (2:3, 3:2, 21:9)**: SeeDream 4.5 only - **Square (1:1)**: Any model (SeeDream, Nano Banana, or Midjourney) ### Q2: How do I generate 4K images with Nano Banana Pro? **A:** ✅ **Use the `size` parameter** with the correct `attribute_id`. Nano Banana Pro supports 3 size options via different `credit_rules`: - **1K** (1024×1024): 10 pts, attribute_id `2399` (default) - **2K** (2048×2048): 10 pts, attribute_id `2400` - **4K** (4096×4096): **18 pts**, attribute_id `2401` **Script usage:** ```bash python3 ima_image_create.py \ --task-type text_to_image \ --model-id gemini-3-pro-image \ --prompt "your prompt" \ --extra-params '{"size": "4K"}' ``` The script automatically selects the correct `attribute_id` (2401) when you specify `size: "4K"`. ### Q3: Can I generate 8K images? **A:** ❌ **No**. No model currently supports 8K resolution. The maximum available is: - **Nano Banana Pro**: 4K (4096×4096) - **SeeDream 4.5 / 4.0 / 3.0**: 4K (adaptive) - **All others**: ≤ 1280×1280 **Workaround**: Generate at maximum resolution (4K), then use external AI upscaling tools (e.g., Real-ESRGAN, Topaz Gigapixel) to upscale to 8K. ### Q4: Which models support custom aspect ratios? **A:** 🌟 **Multiple models now support aspect ratios!** **✅ NATIVE support (no virtual params needed):** - **Nano Banana Pro**: 1:1, 16:9, 9:16, 4:3, 3:4 🆕 - **Nano Banana2**: 1:1, 16:9, 9:16, 4:3, 3:4 🆕 - **Nano Banana MAX**: 1:1, 16:9, 9:16, 4:3, 3:4 🆕 **✅ Virtual parameter mapping (SeeDream):** - **SeeDream 4.5**: 1:1, 16:9, 9:16, 4:3, 3:4, 2:3, 3:2, 21:9, 2k, 4k **❌ NOT supported:** - **Midjourney**: Fixed 1024×1024 (1:1) only **SeeDream 4.5 aspect_ratio support (8 ratios):** - `1:1` → 2048×2048 (square, 5 pts) - `16:9` → 2560×1440 (widescreen, 5 pts) - `9:16` → 1440×2560 (vertical/portrait, 5 pts) - `4:3` → 2304×1728 (classic, 5 pts) - `3:4` → 1728×2304 (vertical, 5 pts) - `2:3` → 1664×2496 (portrait, 5 pts) - `3:2` → 2496×1664 (landscape, 5 pts) - `21:9` → 3024×1296 (ultra-wide, 5 pts) - `2k` / `4k` → Adaptive resolution (5 pts) **Nano Banana series native support (5 ratios):** - `1:1`, `16:9`, `9:16`, `4:3`, `3:4` - No virtual params needed, passed directly to API **Usage:** ```bash # SeeDream 4.5 (virtual params) python3 ima_image_create.py \ --task-type text_to_image \ --model-id doubao-seedream-4.5 \ --prompt "beautiful landscape" \ --extra-params '{"aspect_ratio": "16:9"}' # Nano Banana Pro (native support) python3 ima_image_create.py \ --task-type text_to_image \ --model-id gemini-3-pro-image \ --prompt "beautiful landscape" \ --extra-params '{"aspect_ratio": "16:9"}' ``` **How it works (virtual param mapping for SeeDream):** 1. User provides `aspect_ratio: "16:9"` as input 2. Script queries product list and finds `is_ui_virtual=true` field 3. Applies `value_mapping`: `aspect_ratio: "16:9"` → `size: "2560x1440"` 4. API receives actual parameter: `size: "2560x1440"` **Nano Banana series**: Aspect ratio passed directly, no mapping needed. ### Q5: Why does my `aspect_ratio` parameter get ignored? **A:** Two possibilities: 1. **Model doesn't support it**: Only SeeDream 4.5 and Nano Banana series support custom aspect ratios. Midjourney only supports 1:1 (square). 2. **Virtual param not available in production**: For SeeDream 4.5, the `is_ui_virtual=true` feature may not be deployed yet. If you get 1:1 square output despite requesting 16:9, the API doesn't have the virtual parameter mapping active. **Solution:** - Use **SeeDream 4.5** or **Nano Banana Pro/2/MAX** for aspect ratio needs - Use **video models** with custom aspect ratio, extract first frame - Post-process: Crop or extend the image manually ### Q6: What's the difference between `size` and `resolution`? **A:** - **`size`**: For Nano Banana Pro only. Options: "1K", "2K", "4K". Controls output resolution via different `attribute_id`s. - **`resolution`**: Used in **video models** (e.g., "1080P", "720P", "4K"). Not applicable to text_to_image models. ### Q7: Can I control the aspect ratio after generation? **A:** Not directly in this skill. Options: 1. **Crop**: Take the center/top/bottom portion of the square image to get desired ratio. 2. **Extend (inpainting)**: Use image editing APIs to extend the image to fill the target aspect ratio. 3. **Video workaround**: Use video models with desired aspect ratio, extract first frame. --- ## Common Mistakes | Mistake | Fix | |---------|-----| | Using `attribute_id` not from `credit_rules` | Always fetch product list first | | Placing `prompt` at param top-level | `prompt` must be inside `parameters[].parameters` | | Missing `app` / `platform` in parameters | Required — use `ima` / `web` | | Wrong `credit` value | Must exactly match `credit_rules[].points` (error 6006) | | `size: "adaptive"` for SeeDream 4.5 i2i | Use values from `form_config` options only | | Missing image in both `src_img_url` and `input_images` | Both fields required for image_to_image | --- ## Python Example ```python import time import requests BASE_URL = "https://api.imastudio.com" API_KEY = "ima_your_key_here" HEADERS = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", "x-app-source": "ima_skills", "x_app_language": "en", } def get_products(category: str) -> list: """Returns flat list of type=3 version nodes from V2 tree.""" r = requests.get( f"{BASE_URL}/open/v1/product/list", headers=HEADERS, params={"app": "ima", "platform": "web", "category": category}, ) r.raise_for_status() nodes = r.json()["data"] versions = [] for node in nodes: for child in node.get("children") or []: if child.get("type") == "3": versions.append(child) for gc in child.get("children") or []: if gc.get("type") == "3": versions.append(gc) return versions def create_image_task(task_type: str, prompt: str, product: dict, input_images: list = None, **extra) -> str: """Returns task_id. task_type: 'text_to_image' or 'image_to_image'.""" input_images = input_images or [] rule = product["credit_rules"][0] form_defaults = {f["field"]: f["value"] for f in product.get("form_config", []) if f.get("value") is not None} nested_params = { "prompt": prompt, "n": 1, "input_images": input_images, "cast": {"points": rule["points"], "attribute_id": rule["attribute_id"]}, **form_defaults, } nested_params.update({k: v for k, v in extra.items() if k in ("size",)}) body = { "task_type": task_type, "enable_multi_model": False, "src_img_url": input_images, "parameters": [{ "attribute_id": rule["attribute_id"], "model_id": product["model_id"], "model_name": product["name"], "model_version": product["id"], "app": "ima", "platform": "web", "category": task_type, "credit": rule["points"], "parameters": nested_params, }], } r = requests.post(f"{BASE_URL}/open/v1/tasks/create", headers=HEADERS, json=body) r.raise_for_status() return r.json()["data"]["id"] def poll(task_id: str, interval: int = 3, timeout: int = 300) -> dict: deadline = time.time() + timeout while time.time() < deadline: r = requests.post(f"{BASE_URL}/open/v1/tasks/detail", headers=HEADERS, json={"task_id": task_id}) r.raise_for_status() task = r.json()["data"] medias = task.get("medias", []) if medias: if any(m.get("status") == "failed" for m in medias): raise RuntimeError(f"Task failed: {task_id}") rs = lambda m: m.get("resource_status") if m.get("resource_status") is not None else 0 if any(rs(m) == 2 for m in medias): raise RuntimeError(f"Task failed: {task_id}") if all(rs(m) == 1 for m in medias): return task time.sleep(interval) raise TimeoutError(f"Task timed out: {task_id}") # text_to_image (SeeDream 4.5) products = get_products("text_to_image") task_id = create_image_task("text_to_image", "mountain sunset, photorealistic", products[0]) result = poll(task_id) print(result["medias"][0]["url"]) # text_to_image with Midjourney (artistic style) products = get_products("text_to_image") midjourney = next(p for p in products if p["model_id"] == "midjourney") task_id = create_image_task("text_to_image", "fantasy castle, impressionist painting style", midjourney) result = poll(task_id, interval=8) # Midjourney: poll every 8s print(result["medias"][0]["url"]) # text_to_image with aspect ratio (Nano Banana Pro - native support) products = get_products("text_to_image") nano_pro = next(p for p in products if p["model_id"] == "gemini-3-pro-image") task_id = create_image_task("text_to_image", "beautiful landscape", nano_pro, aspect_ratio="16:9") result = poll(task_id) print(result["medias"][0]["url"]) # image_to_image (size must match form_config options, NOT "adaptive") products = get_products("image_to_image") seedream_i2i = next(p for p in products if p["model_id"] == "doubao-seedream-4.5") task_id = create_image_task( "image_to_image", "turn into oil painting style", seedream_i2i, input_images=["https://example.com/input.jpg","https://example.com/input.jpg"], size="4k", ) result = poll(task_id) print(result["medias"][0]["url"]) # image_to_image with Midjourney (artistic style transfer) products = get_products("image_to_image") midjourney = next(p for p in products if p["model_id"] == "midjourney") task_id = create_image_task( "image_to_image", "anime style, vibrant colors", midjourney, input_images=["https://example.com/portrait.jpg"], ) result = poll(task_id, interval=8) # Midjourney: poll every 8s print(result["medias"][0]["url"]) ``` --- ## Supported Models & Search Terms **Models:** SeeDream 4.5, see dream, Midjourney, MJ, Nano Banana 2, Nano Banana Pro **Capabilities:** image generation, text-to-image, image-to-image, AI art, product photos, character design, logo design, poster, social media graphics, t2i, i2i