Compare commits

...

3 Commits

Author SHA1 Message Date
Jim Liu 宝玉 acf1d42a64 chore: release v1.111.0 2026-04-21 16:44:01 -05:00
Jim Liu 宝玉 adb783ae6d refactor: unify image-backend resolution with preferred_image_backend preference
Replaces the stateless ask-once backend rule with a 4-step resolution
(current-request override > saved preference > auto-select > ask) and
adds a single `preferred_image_backend` field (auto | ask | <backend-id>)
to every image-consuming skill's EXTEND.md schema. Runtime-native tools
(Codex `imagegen`, Hermes `image_generate`, ...) win by default; absent
field equals `auto` so existing user EXTEND.md files stay valid with no
schema version bump.

Each image-consuming skill also gains a top-level `## Changing
Preferences` section as a first-class surface for pinning a backend and
editing common one-line preferences.

Applies across:
  - baoyu-infographic (reverts in-progress two-field image_backend_mode design)
  - baoyu-comic
  - baoyu-cover-image
  - baoyu-image-cards
  - baoyu-article-illustrator
  - baoyu-slide-deck
  - baoyu-xhs-images
  - docs/image-generation-tools.md (canonical author-side doc)
2026-04-21 16:43:58 -05:00
Jim Liu 宝玉 a4bd37c390 chore: release v1.110.0 2026-04-21 15:15:19 -05:00
35 changed files with 509 additions and 126 deletions
+1 -1
View File
@@ -6,7 +6,7 @@
}, },
"metadata": { "metadata": {
"description": "Skills shared by Baoyu for improving daily work efficiency", "description": "Skills shared by Baoyu for improving daily work efficiency",
"version": "1.109.0" "version": "1.111.0"
}, },
"plugins": [ "plugins": [
{ {
+11
View File
@@ -2,6 +2,17 @@
English | [中文](./CHANGELOG.zh.md) English | [中文](./CHANGELOG.zh.md)
## 1.111.0 - 2026-04-21
### Refactor
- Unify image-backend resolution across all image-consuming skills (`baoyu-infographic`, `baoyu-comic`, `baoyu-cover-image`, `baoyu-image-cards`, `baoyu-article-illustrator`, `baoyu-slide-deck`, `baoyu-xhs-images`): add a single `preferred_image_backend` preference field (`auto | ask | <backend-id>`) and replace the stateless ask-once rule with a 4-step resolution (current-request override → saved preference → auto-select → ask). Runtime-native tools (Codex `imagegen`, Hermes `image_generate`) are preferred by default; existing `EXTEND.md` files without the field are treated as `auto` with no schema bump.
- Add a top-level `## Changing Preferences` section to each image-consuming skill as a first-class surface for pinning the backend and editing common one-line preferences.
## 1.110.0 - 2026-04-21
### Features
- `baoyu-imagine`: add `gpt-image-2` support for OpenAI image generation and edits, make it the default OpenAI model, and document the official size/quality mapping, custom-size constraints, and Azure deployment guidance
## 1.109.0 - 2026-04-21 ## 1.109.0 - 2026-04-21
### Features ### Features
+11
View File
@@ -2,6 +2,17 @@
[English](./CHANGELOG.md) | 中文 [English](./CHANGELOG.md) | 中文
## 1.111.0 - 2026-04-21
### 重构
- 统一所有图片生成类技能(`baoyu-infographic``baoyu-comic``baoyu-cover-image``baoyu-image-cards``baoyu-article-illustrator``baoyu-slide-deck``baoyu-xhs-images`)的后端选择规则:新增单一 `preferred_image_backend` 偏好字段(`auto | ask | <backend-id>`),用 4 步解析规则(当前请求覆盖 → 已保存偏好 → 自动选择 → 询问用户)替换原有的无状态询问规则。默认优先使用运行时原生工具(如 Codex `imagegen`、Hermes `image_generate`);未设置该字段的现有 `EXTEND.md` 文件视为 `auto`,无需升级 schema 版本。
- 在每个图片技能中新增顶级 `## Changing Preferences` 章节,作为固定后端和修改常用偏好的一级入口。
## 1.110.0 - 2026-04-21
### 新功能
- `baoyu-imagine`:新增 `gpt-image-2` 支持,用于 OpenAI 图像生成与编辑;将其设为默认 OpenAI 模型,并补齐官方尺寸/质量映射、自定义尺寸约束与 Azure 部署说明
## 1.109.0 - 2026-04-21 ## 1.109.0 - 2026-04-21
### 新功能 ### 新功能
+8 -8
View File
@@ -714,7 +714,7 @@ AI-powered generation backends.
#### baoyu-imagine #### baoyu-imagine
AI SDK-based image generation using OpenAI, Azure OpenAI, Google, OpenRouter, DashScope (Aliyun Tongyi Wanxiang), MiniMax, Jimeng (即梦), Seedream (豆包), and Replicate APIs. Supports text-to-image, reference images, aspect ratios, custom sizes, batch generation, and quality presets. AI SDK-based image generation using OpenAI GPT Image 2, Azure OpenAI, Google, OpenRouter, DashScope (Aliyun Tongyi Wanxiang), MiniMax, Jimeng (即梦), Seedream (豆包), and Replicate APIs. Supports text-to-image, reference images, aspect ratios, custom sizes, batch generation, and quality presets.
```bash ```bash
# Basic generation (auto-detect provider) # Basic generation (auto-detect provider)
@@ -727,10 +727,10 @@ AI SDK-based image generation using OpenAI, Azure OpenAI, Google, OpenRouter, Da
/baoyu-imagine --prompt "A banner" --image banner.png --quality 2k /baoyu-imagine --prompt "A banner" --image banner.png --quality 2k
# Specific provider # Specific provider
/baoyu-imagine --prompt "A cat" --image cat.png --provider openai /baoyu-imagine --prompt "A cat" --image cat.png --provider openai --model gpt-image-2
# Azure OpenAI (model = deployment name) # Azure OpenAI (model = deployment name)
/baoyu-imagine --prompt "A cat" --image cat.png --provider azure --model gpt-image-1.5 /baoyu-imagine --prompt "A cat" --image cat.png --provider azure --model gpt-image-2
# OpenRouter # OpenRouter
/baoyu-imagine --prompt "A cat" --image cat.png --provider openrouter /baoyu-imagine --prompt "A cat" --image cat.png --provider openrouter
@@ -786,7 +786,7 @@ AI SDK-based image generation using OpenAI, Azure OpenAI, Google, OpenRouter, Da
| `--provider` | `google`, `openai`, `azure`, `openrouter`, `dashscope`, `zai`, `minimax`, `jimeng`, `seedream`, or `replicate` | | `--provider` | `google`, `openai`, `azure`, `openrouter`, `dashscope`, `zai`, `minimax`, `jimeng`, `seedream`, or `replicate` |
| `--model`, `-m` | Model ID or deployment name. Azure uses deployment name; OpenRouter uses full model IDs; Z.AI uses `glm-image`; MiniMax uses `image-01` / `image-01-live` | | `--model`, `-m` | Model ID or deployment name. Azure uses deployment name; OpenRouter uses full model IDs; Z.AI uses `glm-image`; MiniMax uses `image-01` / `image-01-live` |
| `--ar` | Aspect ratio (e.g., `16:9`, `1:1`, `4:3`) | | `--ar` | Aspect ratio (e.g., `16:9`, `1:1`, `4:3`) |
| `--size` | Size (e.g., `1024x1024`) | | `--size` | Size (e.g., `1024x1024`; `gpt-image-2` accepts valid custom sizes up to 3840px max edge) |
| `--quality` | `normal` or `2k` (default: `2k`) | | `--quality` | `normal` or `2k` (default: `2k`) |
| `--imageSize` | `1K`, `2K`, or `4K` for Google/OpenRouter | | `--imageSize` | `1K`, `2K`, or `4K` for Google/OpenRouter |
| `--imageApiDialect` | `openai-native` or `ratio-metadata` for OpenAI-compatible gateways | | `--imageApiDialect` | `openai-native` or `ratio-metadata` for OpenAI-compatible gateways |
@@ -810,9 +810,9 @@ AI SDK-based image generation using OpenAI, Azure OpenAI, Google, OpenRouter, Da
| `JIMENG_ACCESS_KEY_ID` | Jimeng Volcengine access key | - | | `JIMENG_ACCESS_KEY_ID` | Jimeng Volcengine access key | - |
| `JIMENG_SECRET_ACCESS_KEY` | Jimeng Volcengine secret key | - | | `JIMENG_SECRET_ACCESS_KEY` | Jimeng Volcengine secret key | - |
| `ARK_API_KEY` | Seedream Volcengine ARK API key | - | | `ARK_API_KEY` | Seedream Volcengine ARK API key | - |
| `OPENAI_IMAGE_MODEL` | OpenAI model | `gpt-image-1.5` | | `OPENAI_IMAGE_MODEL` | OpenAI model | `gpt-image-2` |
| `AZURE_OPENAI_DEPLOYMENT` | Azure default deployment name | - | | `AZURE_OPENAI_DEPLOYMENT` | Azure default deployment name | - |
| `AZURE_OPENAI_IMAGE_MODEL` | Backward-compatible Azure deployment/model alias | `gpt-image-1.5` | | `AZURE_OPENAI_IMAGE_MODEL` | Backward-compatible Azure deployment/model alias | `gpt-image-2` |
| `OPENROUTER_IMAGE_MODEL` | OpenRouter model | `google/gemini-3.1-flash-image-preview` | | `OPENROUTER_IMAGE_MODEL` | OpenRouter model | `google/gemini-3.1-flash-image-preview` |
| `GOOGLE_IMAGE_MODEL` | Google model | `gemini-3-pro-image-preview` | | `GOOGLE_IMAGE_MODEL` | Google model | `gemini-3-pro-image-preview` |
| `DASHSCOPE_IMAGE_MODEL` | DashScope model | `qwen-image-2.0-pro` | | `DASHSCOPE_IMAGE_MODEL` | DashScope model | `qwen-image-2.0-pro` |
@@ -1132,14 +1132,14 @@ mkdir -p ~/.baoyu-skills
cat > ~/.baoyu-skills/.env << 'EOF' cat > ~/.baoyu-skills/.env << 'EOF'
# OpenAI # OpenAI
OPENAI_API_KEY=sk-xxx OPENAI_API_KEY=sk-xxx
OPENAI_IMAGE_MODEL=gpt-image-1.5 OPENAI_IMAGE_MODEL=gpt-image-2
# OPENAI_BASE_URL=https://api.openai.com/v1 # OPENAI_BASE_URL=https://api.openai.com/v1
# OPENAI_IMAGE_USE_CHAT=false # OPENAI_IMAGE_USE_CHAT=false
# Azure OpenAI # Azure OpenAI
AZURE_OPENAI_API_KEY=xxx AZURE_OPENAI_API_KEY=xxx
AZURE_OPENAI_BASE_URL=https://your-resource.openai.azure.com AZURE_OPENAI_BASE_URL=https://your-resource.openai.azure.com
AZURE_OPENAI_DEPLOYMENT=gpt-image-1.5 AZURE_OPENAI_DEPLOYMENT=gpt-image-2
# AZURE_API_VERSION=2025-04-01-preview # AZURE_API_VERSION=2025-04-01-preview
# OpenRouter # OpenRouter
+8 -8
View File
@@ -714,7 +714,7 @@ AI 驱动的生成后端。
#### baoyu-imagine #### baoyu-imagine
基于 AI SDK 的图像生成,支持 OpenAI、Azure OpenAI、Google、OpenRouter、DashScope(阿里通义万相)、MiniMax、即梦(Jimeng)、豆包(Seedream)和 Replicate API。支持文生图、参考图、宽高比、自定义尺寸、批量生成和质量预设。 基于 AI SDK 的图像生成,支持 OpenAI GPT Image 2、Azure OpenAI、Google、OpenRouter、DashScope(阿里通义万相)、MiniMax、即梦(Jimeng)、豆包(Seedream)和 Replicate API。支持文生图、参考图、宽高比、自定义尺寸、批量生成和质量预设。
```bash ```bash
# 基础生成(自动检测服务商) # 基础生成(自动检测服务商)
@@ -727,10 +727,10 @@ AI 驱动的生成后端。
/baoyu-imagine --prompt "横幅图" --image banner.png --quality 2k /baoyu-imagine --prompt "横幅图" --image banner.png --quality 2k
# 指定服务商 # 指定服务商
/baoyu-imagine --prompt "一只猫" --image cat.png --provider openai /baoyu-imagine --prompt "一只猫" --image cat.png --provider openai --model gpt-image-2
# Azure OpenAImodel 为部署名称) # Azure OpenAImodel 为部署名称)
/baoyu-imagine --prompt "一只猫" --image cat.png --provider azure --model gpt-image-1.5 /baoyu-imagine --prompt "一只猫" --image cat.png --provider azure --model gpt-image-2
# OpenRouter # OpenRouter
/baoyu-imagine --prompt "一只猫" --image cat.png --provider openrouter /baoyu-imagine --prompt "一只猫" --image cat.png --provider openrouter
@@ -786,7 +786,7 @@ AI 驱动的生成后端。
| `--provider` | `google``openai``azure``openrouter``dashscope``zai``minimax``jimeng``seedream``replicate` | | `--provider` | `google``openai``azure``openrouter``dashscope``zai``minimax``jimeng``seedream``replicate` |
| `--model`, `-m` | 模型 ID 或部署名。Azure 使用部署名;OpenRouter 使用完整模型 IDZ.AI 使用 `glm-image`MiniMax 使用 `image-01` / `image-01-live` | | `--model`, `-m` | 模型 ID 或部署名。Azure 使用部署名;OpenRouter 使用完整模型 IDZ.AI 使用 `glm-image`MiniMax 使用 `image-01` / `image-01-live` |
| `--ar` | 宽高比(如 `16:9``1:1``4:3` | | `--ar` | 宽高比(如 `16:9``1:1``4:3` |
| `--size` | 尺寸(如 `1024x1024` | | `--size` | 尺寸(如 `1024x1024``gpt-image-2` 支持最长边不超过 3840px 的有效自定义尺寸 |
| `--quality` | `normal``2k`(默认:`2k` | | `--quality` | `normal``2k`(默认:`2k` |
| `--imageSize` | Google/OpenRouter 使用的 `1K``2K``4K` | | `--imageSize` | Google/OpenRouter 使用的 `1K``2K``4K` |
| `--imageApiDialect` | OpenAI 兼容网关的图像 API 方言(`openai-native``ratio-metadata` | | `--imageApiDialect` | OpenAI 兼容网关的图像 API 方言(`openai-native``ratio-metadata` |
@@ -810,9 +810,9 @@ AI 驱动的生成后端。
| `JIMENG_ACCESS_KEY_ID` | 即梦火山引擎 Access Key | - | | `JIMENG_ACCESS_KEY_ID` | 即梦火山引擎 Access Key | - |
| `JIMENG_SECRET_ACCESS_KEY` | 即梦火山引擎 Secret Key | - | | `JIMENG_SECRET_ACCESS_KEY` | 即梦火山引擎 Secret Key | - |
| `ARK_API_KEY` | 豆包火山引擎 ARK API 密钥 | - | | `ARK_API_KEY` | 豆包火山引擎 ARK API 密钥 | - |
| `OPENAI_IMAGE_MODEL` | OpenAI 模型 | `gpt-image-1.5` | | `OPENAI_IMAGE_MODEL` | OpenAI 模型 | `gpt-image-2` |
| `AZURE_OPENAI_DEPLOYMENT` | Azure 默认部署名 | - | | `AZURE_OPENAI_DEPLOYMENT` | Azure 默认部署名 | - |
| `AZURE_OPENAI_IMAGE_MODEL` | 兼容旧配置的 Azure 部署/模型别名 | `gpt-image-1.5` | | `AZURE_OPENAI_IMAGE_MODEL` | 兼容旧配置的 Azure 部署/模型别名 | `gpt-image-2` |
| `OPENROUTER_IMAGE_MODEL` | OpenRouter 模型 | `google/gemini-3.1-flash-image-preview` | | `OPENROUTER_IMAGE_MODEL` | OpenRouter 模型 | `google/gemini-3.1-flash-image-preview` |
| `GOOGLE_IMAGE_MODEL` | Google 模型 | `gemini-3-pro-image-preview` | | `GOOGLE_IMAGE_MODEL` | Google 模型 | `gemini-3-pro-image-preview` |
| `DASHSCOPE_IMAGE_MODEL` | DashScope 模型 | `qwen-image-2.0-pro` | | `DASHSCOPE_IMAGE_MODEL` | DashScope 模型 | `qwen-image-2.0-pro` |
@@ -1132,14 +1132,14 @@ mkdir -p ~/.baoyu-skills
cat > ~/.baoyu-skills/.env << 'EOF' cat > ~/.baoyu-skills/.env << 'EOF'
# OpenAI # OpenAI
OPENAI_API_KEY=sk-xxx OPENAI_API_KEY=sk-xxx
OPENAI_IMAGE_MODEL=gpt-image-1.5 OPENAI_IMAGE_MODEL=gpt-image-2
# OPENAI_BASE_URL=https://api.openai.com/v1 # OPENAI_BASE_URL=https://api.openai.com/v1
# OPENAI_IMAGE_USE_CHAT=false # OPENAI_IMAGE_USE_CHAT=false
# Azure OpenAI # Azure OpenAI
AZURE_OPENAI_API_KEY=xxx AZURE_OPENAI_API_KEY=xxx
AZURE_OPENAI_BASE_URL=https://your-resource.openai.azure.com AZURE_OPENAI_BASE_URL=https://your-resource.openai.azure.com
AZURE_OPENAI_DEPLOYMENT=gpt-image-1.5 AZURE_OPENAI_DEPLOYMENT=gpt-image-2
# AZURE_API_VERSION=2025-04-01-preview # AZURE_API_VERSION=2025-04-01-preview
# OpenRouter # OpenRouter
+23 -5
View File
@@ -4,13 +4,29 @@ Skills in this repo are loaded by multiple agent runtimes (Claude Code, Codex, H
## The Rule ## The Rule
When a skill needs to render an image: When a skill needs to render an image, resolve the backend in this order:
- **Use whatever image-generation tool or skill is available** in the current runtime — e.g., Codex `imagegen`, Hermes `image_generate`, `baoyu-imagine`, or any equivalent the user has installed. 1. **Current-request override** if the user names a specific backend in the current message, use it.
- **If multiple are available**, ask the user **once** at the start which to use (batch with any other initial questions). 2. **Saved preference** — if the skill's `EXTEND.md` sets `preferred_image_backend` to a backend available right now, use it.
- **If none are available**, tell the user and ask how to proceed. 3. **Auto-select** (when the preference is `auto`, unset, or the pinned backend isn't available):
- If the current runtime exposes a native image tool (e.g., Codex `imagegen`, Hermes `image_generate`), use it. Runtime-native tools are preferred by default — agents that know their own tool inventory should surface the native one here.
- Otherwise, if exactly one non-native backend is installed (e.g., `baoyu-imagine`), use it.
- Otherwise (multiple non-native backends with no runtime-native tool), ask the user once — batch with any other initial questions.
4. **If none are available**, tell the user and ask how to proceed.
No explicit priority between runtime-native tools and repo skills — treat them equivalently and let the user decide when there's a choice. No persisted preference mechanism; the question is cheap, and the rule is stateless. Setting `preferred_image_backend: ask` forces the step-3 prompt every run regardless of available backends.
## The Preference Field
Each image-consuming skill's `EXTEND.md` carries a single `preferred_image_backend` field:
| Value | Meaning |
|---|---|
| `auto` (default) | Apply the auto-select rule — runtime-native preferred, fall back to only installed backend, ask if multiple non-native. |
| `ask` | Always confirm the backend on every run, even when a runtime-native tool exists. |
| `<backend-id>` (e.g., `codex-imagegen`, `baoyu-imagine`, `image_generate`) | Pin this backend when available; fall back to `auto` if it isn't. |
The field is **absent-equals-auto**: older `EXTEND.md` files without this field behave exactly as if `preferred_image_backend: auto` were set. No schema version bump is needed to introduce it.
## Prompt File Requirement (hard) ## Prompt File Requirement (hard)
@@ -20,6 +36,8 @@ Regardless of which backend is chosen, every skill that renders images MUST writ
Each `SKILL.md` that renders images includes **exactly one** `## Image Generation Tools` section (near the top, after `## User Input Tools` and before the main workflow) that **inlines** this rule. Skills are self-contained and cannot link to `docs/` — each skill folder must ship the rule inside its own `SKILL.md`. See [CLAUDE.md → Skill Self-Containment](../CLAUDE.md). Each `SKILL.md` that renders images includes **exactly one** `## Image Generation Tools` section (near the top, after `## User Input Tools` and before the main workflow) that **inlines** this rule. Skills are self-contained and cannot link to `docs/` — each skill folder must ship the rule inside its own `SKILL.md`. See [CLAUDE.md → Skill Self-Containment](../CLAUDE.md).
Each skill's `references/config/preferences-schema.md` (and its `EXTEND.md` template in `first-time-setup.md`) lists `preferred_image_backend` alongside other preference fields. First-time setup does NOT ask the user about the backend — `auto` is set silently. Users who want to pin a specific backend edit `EXTEND.md` later, and each skill's `## Changing Preferences` section documents the common one-line edits.
Concrete tool names (`imagegen`, `image_generate`, `baoyu-imagine`) in this document and in SKILL.md are **examples** — agents in other runtimes apply the rule above and substitute the local equivalent. Skill-specific parameters for these backends are illustrative; runtimes without those knobs can omit them. Concrete tool names (`imagegen`, `image_generate`, `baoyu-imagine`) in this document and in SKILL.md are **examples** — agents in other runtimes apply the rule above and substitute the local equivalent. Skill-specific parameters for these backends are illustrative; runtimes without those knobs can omit them.
## Backend Skills Are Exempt ## Backend Skills Are Exempt
+24 -4
View File
@@ -23,11 +23,17 @@ Concrete `AskUserQuestion` references below are examples — substitute the loca
## Image Generation Tools ## Image Generation Tools
When this skill needs to render an image: When this skill needs to render an image, resolve the backend in this order:
- **Use whatever image-generation tool or skill is available** in the current runtime — e.g., Codex `imagegen`, Hermes `image_generate`, `baoyu-imagine`, or any equivalent the user has installed. 1. **Current-request override** if the user names a specific backend in the current message, use it.
- **If multiple are available**, ask the user **once** at the start which to use (batch with any other initial questions). 2. **Saved preference** — if `EXTEND.md` sets `preferred_image_backend` to a backend available right now, use it.
- **If none are available**, tell the user and ask how to proceed. 3. **Auto-select** (when the preference is `auto`, unset, or the pinned backend isn't available):
- If the current runtime exposes a native image tool (e.g., Codex `imagegen`, Hermes `image_generate`), use it. Runtime-native tools are preferred by default — agents that know their own tool inventory should surface the native one here.
- Otherwise, if exactly one non-native backend is installed (e.g., `baoyu-imagine`), use it.
- Otherwise (multiple non-native backends with no runtime-native tool), ask the user once — batch with any other initial questions.
4. **If none are available**, tell the user and ask how to proceed.
Setting `preferred_image_backend: ask` forces the step-3 prompt every run regardless of available backends. Users change the pinned backend via the `## Changing Preferences` section below.
**Prompt file requirement (hard)**: write each image's full, final prompt to a standalone file under `prompts/` (naming: `NN-{type}-[slug].md`) BEFORE invoking any backend. The backend receives the prompt file (or its content); the file is the reproducibility record and lets you switch backends without regenerating prompts. **Prompt file requirement (hard)**: write each image's full, final prompt to a standalone file under `prompts/` (naming: `NN-{type}-[slug].md`) BEFORE invoking any backend. The backend receives the prompt file (or its content); the file is the reproducibility record and lets you switch backends without regenerating prompts.
@@ -207,3 +213,17 @@ When input is **pasted content** (no file path), always uses `illustrations/{top
| [references/style-presets.md](references/style-presets.md) | Preset shortcuts (type + style + palette) | | [references/style-presets.md](references/style-presets.md) | Preset shortcuts (type + style + palette) |
| [references/prompt-construction.md](references/prompt-construction.md) | Prompt templates | | [references/prompt-construction.md](references/prompt-construction.md) | Prompt templates |
| [references/config/first-time-setup.md](references/config/first-time-setup.md) | First-time setup | | [references/config/first-time-setup.md](references/config/first-time-setup.md) | First-time setup |
## Changing Preferences
EXTEND.md lives at the first matching path listed in Step 1.5. Three ways to change it:
- **Edit directly** — open EXTEND.md and change fields. Full schema: `references/config/preferences-schema.md`.
- **Reconfigure interactively** — delete EXTEND.md (or ask "reconfigure baoyu-article-illustrator preferences" / "重新配置"). The next run re-triggers first-time setup.
- **Common one-line edits**:
- `preferred_image_backend: auto` — default; runtime-native tool wins, falls back to the only installed backend, asks only if multiple non-native are present.
- `preferred_image_backend: codex-imagegen` — pin to Codex's built-in.
- `preferred_image_backend: baoyu-imagine` — pin to the baoyu-imagine skill.
- `preferred_image_backend: ask` — confirm backend every run.
- `preferred_type: infographic`, `preferred_style: notion`, `preferred_palette: macaron`, `language: zh`.
- `default_output_dir: imgs-subdir` — where to write generated images relative to the article.
@@ -126,13 +126,13 @@ preferred_style:
description: "" description: ""
default_output_dir: imgs-subdir # same-dir | imgs-subdir | illustrations-subdir | independent default_output_dir: imgs-subdir # same-dir | imgs-subdir | illustrations-subdir | independent
language: null language: null
preferred_image_backend: auto
custom_styles: [] custom_styles: []
--- ---
``` ```
`preferred_image_backend: auto` is the baked-in default — first-time setup does not ask about it. The `## Image Generation Tools` rule in SKILL.md then picks the runtime-native tool (Codex `imagegen`, Hermes `image_generate`, etc.) when available, and falls back to installed backends.
## Modifying Preferences Later ## Modifying Preferences Later
Users can edit EXTEND.md directly or run setup again: See the `## Changing Preferences` section in `SKILL.md` for the canonical list of common edits (pin backend, change defaults, retrigger setup). Full schema: `preferences-schema.md`.
- Delete EXTEND.md to trigger setup
- Edit YAML frontmatter for quick changes
- Full schema: `config/preferences-schema.md`
@@ -26,6 +26,8 @@ language: null # zh|en|ja|ko|auto
default_output_dir: null # same-dir|illustrations-subdir|independent default_output_dir: null # same-dir|illustrations-subdir|independent
preferred_image_backend: auto # auto|ask|<backend-id>
custom_styles: custom_styles:
- name: my-style - name: my-style
description: "Style description" description: "Style description"
@@ -52,6 +54,7 @@ custom_styles:
| `preferred_palette` | string | null | Palette override (macaron, warm, neon, or null) | | `preferred_palette` | string | null | Palette override (macaron, warm, neon, or null) |
| `language` | string | null | Output language (null = auto-detect) | | `language` | string | null | Output language (null = auto-detect) |
| `default_output_dir` | enum | null | Output directory preference (null = ask each time) | | `default_output_dir` | enum | null | Output directory preference (null = ask each time) |
| `preferred_image_backend` | string | `auto` | Image backend selection. `auto` = prefer runtime-native tool, fall back to the only installed backend, ask if multiple non-native are present. `ask` = always confirm on every run. `<backend-id>` (e.g., `codex-imagegen`, `baoyu-imagine`, `image_generate`) = pin this backend when available; fall back to `auto` when it isn't. Absent = `auto`. Resolution logic is documented in `SKILL.md`'s `## Image Generation Tools` section. |
| `custom_styles` | array | [] | User-defined styles | | `custom_styles` | array | [] | User-defined styles |
## Position Options ## Position Options
@@ -113,6 +116,8 @@ preferred_style:
language: zh language: zh
preferred_image_backend: codex-imagegen
custom_styles: custom_styles:
- name: corporate - name: corporate
description: "Professional B2B style" description: "Professional B2B style"
+23 -4
View File
@@ -27,11 +27,17 @@ Concrete `AskUserQuestion` references below are examples — substitute the loca
## Image Generation Tools ## Image Generation Tools
When this skill needs to render an image: When this skill needs to render an image, resolve the backend in this order:
- **Use whatever image-generation tool or skill is available** in the current runtime — e.g., Codex `imagegen`, Hermes `image_generate`, `baoyu-imagine`, or any equivalent the user has installed. 1. **Current-request override** if the user names a specific backend in the current message, use it.
- **If multiple are available**, ask the user **once** at the start which to use (batch with any other initial questions). 2. **Saved preference** — if `EXTEND.md` sets `preferred_image_backend` to a backend available right now, use it.
- **If none are available**, tell the user and ask how to proceed. 3. **Auto-select** (when the preference is `auto`, unset, or the pinned backend isn't available):
- If the current runtime exposes a native image tool (e.g., Codex `imagegen`, Hermes `image_generate`), use it. Runtime-native tools are preferred by default — agents that know their own tool inventory should surface the native one here.
- Otherwise, if exactly one non-native backend is installed (e.g., `baoyu-imagine`), use it.
- Otherwise (multiple non-native backends with no runtime-native tool), ask the user once — batch with any other initial questions.
4. **If none are available**, tell the user and ask how to proceed.
Setting `preferred_image_backend: ask` forces the step-3 prompt every run regardless of available backends. Users change the pinned backend via the `## Changing Preferences` section below.
**Prompt file requirement (hard)**: write each image's full, final prompt to a standalone file under `prompts/` (naming: `NN-{type}-[slug].md`) BEFORE invoking any backend. The backend receives the prompt file (or its content); the file is the reproducibility record and lets you switch backends without regenerating prompts. **Prompt file requirement (hard)**: write each image's full, final prompt to a standalone file under `prompts/` (naming: `NN-{type}-[slug].md`) BEFORE invoking any backend. The backend receives the prompt file (or its content); the file is the reproducibility record and lets you switch backends without regenerating prompts.
@@ -295,3 +301,16 @@ If EXTEND.md is not found, first-time setup is **blocking** — complete it befo
- **Step 7.1 character sheet** - recommended for multi-page comics, optional for simple presets - **Step 7.1 character sheet** - recommended for multi-page comics, optional for simple presets
- **Step 7.2 character reference** - use `--ref` if sheet exists; compress/convert on failure; fall back to prompt-only - **Step 7.2 character reference** - use `--ref` if sheet exists; compress/convert on failure; fall back to prompt-only
- Watermark/language configured once in EXTEND.md - Watermark/language configured once in EXTEND.md
## Changing Preferences
EXTEND.md lives at `.baoyu-skills/baoyu-comic/EXTEND.md` (project) or `~/.baoyu-skills/baoyu-comic/EXTEND.md` (user). Three ways to change it:
- **Edit directly** — open EXTEND.md and change fields. Full schema: `references/config/preferences-schema.md`.
- **Reconfigure interactively** — delete EXTEND.md (or ask "reconfigure baoyu-comic preferences" / "重新配置"). The next run re-triggers first-time setup.
- **Common one-line edits**:
- `preferred_image_backend: auto` — default; runtime-native tool wins, falls back to the only installed backend, asks only if multiple non-native are present.
- `preferred_image_backend: codex-imagegen` — pin to Codex's built-in.
- `preferred_image_backend: baoyu-imagine` — pin to the baoyu-imagine skill.
- `preferred_image_backend: ask` — confirm backend every run.
- `watermark.enabled: true`, `preferred_art`, `preferred_tone`, `preferred_layout`, `language` — shift the auto-selection defaults and cosmetic choices.
@@ -142,13 +142,13 @@ preferred_tone: [selected tone or null]
preferred_layout: null preferred_layout: null
preferred_aspect: null preferred_aspect: null
language: [selected or null] language: [selected or null]
preferred_image_backend: auto
character_presets: [] character_presets: []
--- ---
``` ```
`preferred_image_backend: auto` is the baked-in default — first-time setup does not ask about it. The `## Image Generation Tools` rule in SKILL.md then picks the runtime-native tool (Codex `imagegen`, Hermes `image_generate`, etc.) when available, and falls back to installed backends.
## Modifying Preferences Later ## Modifying Preferences Later
Users can edit EXTEND.md directly or run setup again: See the `## Changing Preferences` section in `SKILL.md` for the canonical list of common edits (pin backend, change defaults, retrigger setup). Full schema: `config/preferences-schema.md`.
- Delete EXTEND.md to trigger setup
- Edit YAML frontmatter for quick changes
- Full schema: `config/preferences-schema.md`
@@ -23,6 +23,8 @@ preferred_aspect: null # 3:4|4:3|16:9
language: null # zh|en|ja|ko|auto language: null # zh|en|ja|ko|auto
preferred_image_backend: auto # auto|ask|<backend-id>
character_presets: character_presets:
- name: my-characters - name: my-characters
roles: roles:
@@ -46,6 +48,7 @@ character_presets:
| `preferred_layout` | string | null | Layout preference or null | | `preferred_layout` | string | null | Layout preference or null |
| `preferred_aspect` | string | null | Aspect ratio (3:4, 4:3, 16:9) | | `preferred_aspect` | string | null | Aspect ratio (3:4, 4:3, 16:9) |
| `language` | string | null | Output language (null = auto-detect) | | `language` | string | null | Output language (null = auto-detect) |
| `preferred_image_backend` | string | `auto` | Image backend selection. `auto` = prefer runtime-native tool, fall back to the only installed backend, ask if multiple non-native are present. `ask` = always confirm on every run. `<backend-id>` (e.g., `codex-imagegen`, `baoyu-imagine`, `image_generate`) = pin this backend when available; fall back to `auto` when it isn't. Absent = `auto`. Resolution logic is documented in `SKILL.md`'s `## Image Generation Tools` section. |
| `character_presets` | array | [] | Preset character roles for styles like ohmsha | | `character_presets` | array | [] | Preset character roles for styles like ohmsha |
## Art Style Options ## Art Style Options
@@ -122,6 +125,8 @@ preferred_aspect: "3:4"
language: zh language: zh
preferred_image_backend: codex-imagegen
character_presets: character_presets:
- name: tech-tutorial - name: tech-tutorial
roles: roles:
+20 -9
View File
@@ -23,11 +23,17 @@ Concrete `AskUserQuestion` references below are examples — substitute the loca
## Image Generation Tools ## Image Generation Tools
When this skill needs to render an image: When this skill needs to render an image, resolve the backend in this order:
- **Use whatever image-generation tool or skill is available** in the current runtime — e.g., Codex `imagegen`, Hermes `image_generate`, `baoyu-imagine`, or any equivalent the user has installed. 1. **Current-request override** if the user names a specific backend in the current message, use it.
- **If multiple are available**, ask the user **once** at the start which to use (batch with any other initial questions). 2. **Saved preference** — if `EXTEND.md` sets `preferred_image_backend` to a backend available right now, use it.
- **If none are available**, tell the user and ask how to proceed. 3. **Auto-select** (when the preference is `auto`, unset, or the pinned backend isn't available):
- If the current runtime exposes a native image tool (e.g., Codex `imagegen`, Hermes `image_generate`), use it. Runtime-native tools are preferred by default — agents that know their own tool inventory should surface the native one here.
- Otherwise, if exactly one non-native backend is installed (e.g., `baoyu-imagine`), use it.
- Otherwise (multiple non-native backends with no runtime-native tool), ask the user once — batch with any other initial questions.
4. **If none are available**, tell the user and ask how to proceed.
Setting `preferred_image_backend: ask` forces the step-3 prompt every run regardless of available backends. Users change the pinned backend via the `## Changing Preferences` section below.
**Prompt file requirement (hard)**: write each image's full, final prompt to a standalone file under `prompts/` (naming: `NN-{type}-[slug].md`) BEFORE invoking any backend. The backend receives the prompt file (or its content); the file is the reproducibility record and lets you switch backends without regenerating prompts. **Prompt file requirement (hard)**: write each image's full, final prompt to a standalone file under `prompts/` (naming: `NN-{type}-[slug].md`) BEFORE invoking any backend. The backend receives the prompt file (or its content); the file is the reproducibility record and lets you switch backends without regenerating prompts.
@@ -228,13 +234,18 @@ Files:
- **Characters**: Simplified silhouettes; NO realistic humans - **Characters**: Simplified silhouettes; NO realistic humans
- **Title**: Use exact title from user/source; never invent - **Title**: Use exact title from user/source; never invent
## Extension Support ## Changing Preferences
Custom configurations via EXTEND.md. See **Step 0** for paths. EXTEND.md lives at the path noted in **Step 0**. Three ways to change it:
Supports: Watermark | Preferred dimensions | Default aspect/output | Quick mode | Custom palettes | Language - **Edit directly** — open EXTEND.md and change fields. Full schema: [references/config/preferences-schema.md](references/config/preferences-schema.md).
- **Reconfigure interactively** — delete EXTEND.md (or ask "reconfigure baoyu-cover-image preferences" / "重新配置"). The next run re-triggers first-time setup.
Schema: [references/config/preferences-schema.md](references/config/preferences-schema.md) - **Common one-line edits**:
- `preferred_image_backend: auto` — default; runtime-native tool wins, falls back to the only installed backend, asks only if multiple non-native are present.
- `preferred_image_backend: codex-imagegen` — pin to Codex's built-in.
- `preferred_image_backend: baoyu-imagine` — pin to the baoyu-imagine skill.
- `preferred_image_backend: ask` — confirm backend every run.
- `watermark.enabled: true`, `preferred_type`, `preferred_palette`, `preferred_rendering`, `default_aspect`, `quick_mode: true`, `language` — shift the auto-selection defaults and confirmation flow.
## References ## References
@@ -188,15 +188,15 @@ default_aspect: [16:9/2.35:1/1:1/3:4]
default_output_dir: [independent/same-dir/imgs-subdir] default_output_dir: [independent/same-dir/imgs-subdir]
quick_mode: [true/false] quick_mode: [true/false]
language: null language: null
preferred_image_backend: auto
custom_palettes: [] custom_palettes: []
--- ---
``` ```
`preferred_image_backend: auto` is the baked-in default — first-time setup does not ask about it. The `## Image Generation Tools` rule in SKILL.md then picks the runtime-native tool (Codex `imagegen`, Hermes `image_generate`, etc.) when available, and falls back to installed backends.
## Modifying Preferences Later ## Modifying Preferences Later
Users can edit EXTEND.md directly or run setup again: See the `## Changing Preferences` section in `SKILL.md` for the canonical list of common edits (pin backend, change defaults, retrigger setup). Full schema: `preferences-schema.md`.
- Delete EXTEND.md to trigger setup
- Edit YAML frontmatter for quick changes
- Full schema: `preferences-schema.md`
**EXTEND.md Supports**: Watermark | Preferred type | Preferred palette | Preferred rendering | Preferred text | Preferred mood | Default aspect ratio | Default output directory | Quick mode | Custom palette definitions | Language preference **EXTEND.md Supports**: Watermark | Preferred type | Preferred palette | Preferred rendering | Preferred text | Preferred mood | Default aspect ratio | Default output directory | Quick mode | Image backend preference | Custom palette definitions | Language preference
@@ -32,6 +32,8 @@ quick_mode: false # Skip confirmation when true
language: null # zh|en|ja|ko|auto (null = auto-detect) language: null # zh|en|ja|ko|auto (null = auto-detect)
preferred_image_backend: auto # auto|ask|<backend-id>
custom_palettes: custom_palettes:
- name: my-palette - name: my-palette
description: "Palette description" description: "Palette description"
@@ -60,6 +62,7 @@ custom_palettes:
| `default_aspect` | string | "2.35:1" | Default aspect ratio | | `default_aspect` | string | "2.35:1" | Default aspect ratio |
| `quick_mode` | bool | false | Skip confirmation step | | `quick_mode` | bool | false | Skip confirmation step |
| `language` | string | null | Output language (null = auto-detect) | | `language` | string | null | Output language (null = auto-detect) |
| `preferred_image_backend` | string | `auto` | Image backend selection. `auto` = prefer runtime-native tool, fall back to the only installed backend, ask if multiple non-native are present. `ask` = always confirm on every run. `<backend-id>` (e.g., `codex-imagegen`, `baoyu-imagine`, `image_generate`) = pin this backend when available; fall back to `auto` when it isn't. Absent = `auto`. Resolution logic is documented in `SKILL.md`'s `## Image Generation Tools` section. |
| `custom_palettes` | array | [] | User-defined palettes | | `custom_palettes` | array | [] | User-defined palettes |
## Type Options ## Type Options
@@ -187,6 +190,8 @@ quick_mode: true
language: en language: en
preferred_image_backend: codex-imagegen
custom_palettes: custom_palettes:
- name: corporate-tech - name: corporate-tech
description: "Professional B2B tech palette" description: "Professional B2B tech palette"
+25 -5
View File
@@ -23,14 +23,22 @@ Concrete `AskUserQuestion` references below are examples — substitute the loca
## Image Generation Tools ## Image Generation Tools
When this skill needs to render an image: When this skill needs to render an image, resolve the backend in this order:
- **Use whatever image-generation tool or skill is available** in the current runtime — e.g., Codex `imagegen`, Hermes `image_generate`, `baoyu-imagine`, or any equivalent the user has installed. 1. **Current-request override** if the user names a specific backend in the current message, use it.
- **If multiple are available**, ask the user **once** at the start which to use (batch with any other initial questions). 2. **Saved preference** — if `EXTEND.md` sets `preferred_image_backend` to a backend available right now, use it.
- **If none are available**, tell the user and ask how to proceed. 3. **Auto-select** (when the preference is `auto`, unset, or the pinned backend isn't available):
- If the current runtime exposes a native image tool (e.g., Codex `imagegen`, Hermes `image_generate`), use it. Runtime-native tools are preferred by default — agents that know their own tool inventory should surface the native one here.
- Otherwise, if exactly one non-native backend is installed (e.g., `baoyu-imagine`), use it.
- Otherwise (multiple non-native backends with no runtime-native tool), ask the user once — batch with any other initial questions.
4. **If none are available**, tell the user and ask how to proceed.
Setting `preferred_image_backend: ask` forces the step-3 prompt every run regardless of available backends. Users change the pinned backend via the `## Changing Preferences` section below.
**Prompt file requirement (hard)**: write each image's full, final prompt to a standalone file under `prompts/` (naming: `NN-{type}-[slug].md`) BEFORE invoking any backend. The file is the reproducibility record and lets you switch backends without regenerating prompts. **Prompt file requirement (hard)**: write each image's full, final prompt to a standalone file under `prompts/` (naming: `NN-{type}-[slug].md`) BEFORE invoking any backend. The file is the reproducibility record and lets you switch backends without regenerating prompts.
Concrete tool names (`imagegen`, `image_generate`, `baoyu-imagine`) above are examples — substitute the local equivalents under the same rule.
## Language ## Language
Respond in the user's language across questions, progress, errors, and completion summary. Keep technical tokens (style names, file paths, code) in English. Respond in the user's language across questions, progress, errors, and completion summary. Keep technical tokens (style names, file paths, code) in English.
@@ -417,4 +425,16 @@ Always update the prompt file before regenerating — it's the source of truth a
- For sensitive public figures, use stylized cartoon alternatives. - For sensitive public figures, use stylized cartoon alternatives.
- Smart Confirm (Step 2) is required; Detailed mode adds a second confirmation (2a + 2c). - Smart Confirm (Step 2) is required; Detailed mode adds a second confirmation (2a + 2c).
Custom configurations via EXTEND.md. See Step 0 for paths and schema. ## Changing Preferences
EXTEND.md lives at the first matching path listed in Step 0. Three ways to change it:
- **Edit directly** — open EXTEND.md and change fields. Full schema: `references/config/preferences-schema.md`.
- **Reconfigure interactively** — delete EXTEND.md (or ask "reconfigure baoyu-image-cards preferences" / "重新配置"). The next run re-triggers first-time setup.
- **Common one-line edits**:
- `preferred_image_backend: auto` — default; runtime-native tool wins, falls back to the only installed backend, asks only if multiple non-native are present.
- `preferred_image_backend: codex-imagegen` — pin to Codex's built-in.
- `preferred_image_backend: baoyu-imagine` — pin to the baoyu-imagine skill.
- `preferred_image_backend: ask` — confirm backend every run.
- `preferred_style: notion`, `preferred_layout: dense`, `preferred_palette: macaron`, `language: zh`.
- `watermark.enabled: true` + `watermark.content: "@handle"` — add a watermark.
@@ -110,13 +110,13 @@ preferred_style:
description: "" description: ""
preferred_layout: null preferred_layout: null
language: null language: null
preferred_image_backend: auto
custom_styles: [] custom_styles: []
--- ---
``` ```
`preferred_image_backend: auto` is the baked-in default — first-time setup does not ask about it. The `## Image Generation Tools` rule in SKILL.md then picks the runtime-native tool (Codex `imagegen`, Hermes `image_generate`, etc.) when available, and falls back to installed backends.
## Modifying Preferences Later ## Modifying Preferences Later
Users can edit EXTEND.md directly or run setup again: See the `## Changing Preferences` section in `SKILL.md` for the canonical list of common edits (pin backend, change defaults, retrigger setup). Full schema: `preferences-schema.md`.
- Delete EXTEND.md to trigger setup
- Edit YAML frontmatter for quick changes
- Full schema: `config/preferences-schema.md`
@@ -24,6 +24,8 @@ preferred_layout: null # sparse|balanced|dense|list|comparison|flow
language: null # zh|en|ja|ko|auto language: null # zh|en|ja|ko|auto
preferred_image_backend: auto # auto|ask|<backend-id>
custom_styles: custom_styles:
- name: my-style - name: my-style
description: "Style description" description: "Style description"
@@ -49,6 +51,7 @@ custom_styles:
| `preferred_style.description` | string | "" | Custom notes/override | | `preferred_style.description` | string | "" | Custom notes/override |
| `preferred_layout` | string | null | Layout preference or null | | `preferred_layout` | string | null | Layout preference or null |
| `language` | string | null | Output language (null = auto-detect) | | `language` | string | null | Output language (null = auto-detect) |
| `preferred_image_backend` | string | `auto` | Image backend selection. `auto` = prefer runtime-native tool, fall back to the only installed backend, ask if multiple non-native are present. `ask` = always confirm on every run. `<backend-id>` (e.g., `codex-imagegen`, `baoyu-imagine`, `image_generate`) = pin this backend when available; fall back to `auto` when it isn't. Absent = `auto`. Resolution logic is documented in `SKILL.md`'s `## Image Generation Tools` section. |
| `custom_styles` | array | [] | User-defined styles | | `custom_styles` | array | [] | User-defined styles |
## Position Options ## Position Options
@@ -104,6 +107,8 @@ preferred_layout: dense
language: zh language: zh
preferred_image_backend: codex-imagegen
custom_styles: custom_styles:
- name: corporate - name: corporate
description: "Professional B2B style" description: "Professional B2B style"
+15 -8
View File
@@ -1,7 +1,7 @@
--- ---
name: baoyu-imagine name: baoyu-imagine
description: AI image generation with OpenAI, Azure OpenAI, Google, OpenRouter, DashScope, Z.AI GLM-Image, MiniMax, Jimeng, Seedream and Replicate APIs. Supports text-to-image, reference images, aspect ratios, and batch generation from saved prompt files. Sequential by default; use batch parallel generation when the user already has multiple prompts or wants stable multi-image throughput. Use when user asks to generate, create, or draw images. description: AI image generation with OpenAI GPT Image 2, Azure OpenAI, Google, OpenRouter, DashScope, Z.AI GLM-Image, MiniMax, Jimeng, Seedream and Replicate APIs. Supports text-to-image, reference images, aspect ratios, and batch generation from saved prompt files. Sequential by default; use batch parallel generation when the user already has multiple prompts or wants stable multi-image throughput. Use when user asks to generate, create, or draw images.
version: 1.57.0 version: 1.58.0
metadata: metadata:
openclaw: openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-imagine homepage: https://github.com/JimLiu/baoyu-skills#baoyu-imagine
@@ -13,7 +13,7 @@ metadata:
# Image Generation (AI SDK) # Image Generation (AI SDK)
Official API-based image generation. Supports OpenAI, Azure OpenAI, Google, OpenRouter, DashScope (阿里通义万象), Z.AI GLM-Image, MiniMax, Jimeng (即梦), Seedream (豆包) and Replicate. Official API-based image generation. Supports OpenAI GPT Image 2, Azure OpenAI, Google, OpenRouter, DashScope (阿里通义万象), Z.AI GLM-Image, MiniMax, Jimeng (即梦), Seedream (豆包) and Replicate.
## User Input Tools ## User Input Tools
@@ -68,6 +68,9 @@ ${BUN_X} {baseDir}/scripts/main.ts --prompt "Make blue" --image out.png --ref so
# Specific provider # Specific provider
${BUN_X} {baseDir}/scripts/main.ts --prompt "A cat" --image out.png --provider dashscope --model qwen-image-2.0-pro ${BUN_X} {baseDir}/scripts/main.ts --prompt "A cat" --image out.png --provider dashscope --model qwen-image-2.0-pro
# OpenAI GPT Image 2
${BUN_X} {baseDir}/scripts/main.ts --prompt "A cat" --image out.png --provider openai --model gpt-image-2
# Batch mode # Batch mode
${BUN_X} {baseDir}/scripts/main.ts --batchfile batch.json --jobs 4 ${BUN_X} {baseDir}/scripts/main.ts --batchfile batch.json --jobs 4
``` ```
@@ -84,7 +87,7 @@ ${BUN_X} {baseDir}/scripts/main.ts --batchfile batch.json --jobs 4
| `--provider google\|openai\|azure\|openrouter\|dashscope\|zai\|minimax\|jimeng\|seedream\|replicate` | Force provider (default: auto-detect) | | `--provider google\|openai\|azure\|openrouter\|dashscope\|zai\|minimax\|jimeng\|seedream\|replicate` | Force provider (default: auto-detect) |
| `--model <id>`, `-m` | Model ID — see provider references for defaults and allowed values | | `--model <id>`, `-m` | Model ID — see provider references for defaults and allowed values |
| `--ar <ratio>` | Aspect ratio (`16:9`, `1:1`, `4:3`, …) | | `--ar <ratio>` | Aspect ratio (`16:9`, `1:1`, `4:3`, …) |
| `--size <WxH>` | Explicit size (e.g., `1024x1024`) | | `--size <WxH>` | Explicit size (e.g., `1024x1024`; for `gpt-image-2`, width/height must be multiples of 16, max edge 3840px, ratio no wider than 3:1) |
| `--quality normal\|2k` | Quality preset (default: `2k`) | | `--quality normal\|2k` | Quality preset (default: `2k`) |
| `--imageSize 1K\|2K\|4K` | Image size for Google/OpenRouter (default: from quality) | | `--imageSize 1K\|2K\|4K` | Image size for Google/OpenRouter (default: from quality) |
| `--imageApiDialect openai-native\|ratio-metadata` | OpenAI-compatible endpoint dialect — use `ratio-metadata` for gateways that expect aspect-ratio `size` plus `metadata.resolution` | | `--imageApiDialect openai-native\|ratio-metadata` | OpenAI-compatible endpoint dialect — use `ratio-metadata` for gateways that expect aspect-ratio `size` plus `metadata.resolution` |
@@ -128,7 +131,9 @@ Priority (highest → lowest) applies to every provider:
3. Env var `<PROVIDER>_IMAGE_MODEL` 3. Env var `<PROVIDER>_IMAGE_MODEL`
4. Built-in default 4. Built-in default
For Azure, `--model` / `default_model.azure` is the Azure deployment name. `AZURE_OPENAI_DEPLOYMENT` is the preferred env var; `AZURE_OPENAI_IMAGE_MODEL` is kept as a backward-compatible alias. For OpenAI, the built-in default is `gpt-image-2`. `gpt-image-1.5`, `gpt-image-1`, and GPT Image snapshots remain selectable with `--model` or `OPENAI_IMAGE_MODEL`.
For Azure, `--model` / `default_model.azure` is the Azure deployment name. `AZURE_OPENAI_DEPLOYMENT` is the preferred env var; `AZURE_OPENAI_IMAGE_MODEL` is kept as a backward-compatible alias. If your Azure deployment is named after the underlying model, use `gpt-image-2`; otherwise use the exact custom deployment name.
EXTEND.md overrides env vars: if EXTEND.md sets `default_model.google: "gemini-3-pro-image-preview"` and the env var sets `GOOGLE_IMAGE_MODEL=gemini-3.1-flash-image-preview`, EXTEND.md wins. EXTEND.md overrides env vars: if EXTEND.md sets `default_model.google: "gemini-3-pro-image-preview"` and the env var sets `GOOGLE_IMAGE_MODEL=gemini-3.1-flash-image-preview`, EXTEND.md wins.
@@ -169,17 +174,19 @@ Each provider has its own quirks (model families, size rules, ref support, limit
| Preset | Google imageSize | OpenAI size | OpenRouter size | Replicate resolution | Use case | | Preset | Google imageSize | OpenAI size | OpenRouter size | Replicate resolution | Use case |
|--------|------------------|-------------|-----------------|----------------------|----------| |--------|------------------|-------------|-----------------|----------------------|----------|
| `normal` | 1K | 1024px | 1K | 1K | Quick previews | | `normal` | 1K | 1024px target | 1K | 1K | Quick previews |
| `2k` (default) | 2K | 2048px | 2K | 2K | Covers, illustrations, infographics | | `2k` (default) | 2K | 2048px target | 2K | 2K | Covers, illustrations, infographics |
Google/OpenRouter `imageSize` can be overridden with `--imageSize 1K|2K|4K`. Google/OpenRouter `imageSize` can be overridden with `--imageSize 1K|2K|4K`.
For OpenAI native `gpt-image-2`, `normal` maps to `quality=medium` and a low-latency valid size near the requested aspect ratio; `2k` maps to `quality=high` and 2048px-class sizes such as `2048x2048`, `2048x1152`, or `1152x2048`. Use explicit `--size` for valid custom or 4K outputs, e.g. `3840x2160`.
## Aspect Ratios ## Aspect Ratios
Supported: `1:1`, `16:9`, `9:16`, `4:3`, `3:4`, `2.35:1`. Supported: `1:1`, `16:9`, `9:16`, `4:3`, `3:4`, `2.35:1`.
- Google multimodal: `imageConfig.aspectRatio` - Google multimodal: `imageConfig.aspectRatio`
- OpenAI: closest supported size - OpenAI: `gpt-image-2` uses the closest valid custom size for the requested ratio; older GPT Image and DALL·E models use their closest supported fixed size
- OpenRouter: `imageGenerationOptions.aspect_ratio`; if only `--size <WxH>` is given, the ratio is inferred - OpenRouter: `imageGenerationOptions.aspect_ratio`; if only `--size <WxH>` is given, the ratio is inferred
- Replicate: behavior is model-specific — `google/nano-banana*` uses `aspect_ratio`, `bytedance/seedream-*` uses documented Replicate ratios, Wan 2.7 maps `--ar` to a concrete `size` - Replicate: behavior is model-specific — `google/nano-banana*` uses `aspect_ratio`, `bytedance/seedream-*` uses documented Replicate ratios, Wan 2.7 maps `--ar` to a concrete `size`
- MiniMax: official `aspect_ratio` values; if `--size <WxH>` is given without `--ar`, sends `width`/`height` for `image-01` - MiniMax: official `aspect_ratio` values; if `--size <WxH>` is given without `--ar`, sends `width`/`height` for `image-01`
@@ -46,7 +46,7 @@ options:
- label: "Google (Recommended)" - label: "Google (Recommended)"
description: "Gemini multimodal - high quality, reference images, flexible sizes" description: "Gemini multimodal - high quality, reference images, flexible sizes"
- label: "OpenAI" - label: "OpenAI"
description: "GPT Image - consistent quality, reliable output" description: "GPT Image 2 - latest OpenAI image model, reference-image workflows"
- label: "Azure OpenAI" - label: "Azure OpenAI"
description: "Azure-hosted GPT Image deployments with resource-specific routing" description: "Azure-hosted GPT Image deployments with resource-specific routing"
- label: "OpenRouter" - label: "OpenRouter"
@@ -101,10 +101,12 @@ Only show if user selected Azure OpenAI.
header: "Azure Deploy" header: "Azure Deploy"
question: "Default Azure image deployment name?" question: "Default Azure image deployment name?"
options: options:
- label: "gpt-image-1.5 (Recommended)" - label: "gpt-image-2 (Recommended)"
description: "Best default if your Azure deployment uses the same name" description: "Use if your Azure deployment uses the GPT Image 2 model name"
- label: "gpt-image-1" - label: "gpt-image-1.5"
description: "Previous GPT Image deployment name" description: "Previous GPT Image deployment name"
- label: "gpt-image-1"
description: "Earlier GPT Image deployment name"
``` ```
### Question 2d: Default MiniMax Model ### Question 2d: Default MiniMax Model
@@ -214,10 +216,12 @@ options:
header: "OpenAI Model" header: "OpenAI Model"
question: "Choose a default OpenAI image generation model?" question: "Choose a default OpenAI image generation model?"
options: options:
- label: "gpt-image-1.5 (Recommended)" - label: "gpt-image-2 (Recommended)"
description: "Latest GPT Image model, high quality" description: "Latest GPT Image model, flexible sizes up to 4K, high-fidelity image inputs"
- label: "gpt-image-1.5"
description: "Previous GPT Image model"
- label: "gpt-image-1" - label: "gpt-image-1"
description: "Previous generation GPT Image model" description: "Earlier GPT Image model"
``` ```
### Azure Deployment Selection ### Azure Deployment Selection
@@ -226,8 +230,10 @@ options:
header: "Azure Deploy" header: "Azure Deploy"
question: "Choose a default Azure image deployment name?" question: "Choose a default Azure image deployment name?"
options: options:
- label: "gpt-image-1.5 (Recommended)" - label: "gpt-image-2 (Recommended)"
description: "Use when your Azure deployment name matches the GPT-image-1.5 model" description: "Use when your Azure deployment name matches the GPT Image 2 model"
- label: "gpt-image-1.5"
description: "Use when your Azure deployment name matches the GPT Image 1.5 model"
- label: "gpt-image-1" - label: "gpt-image-1"
description: "Use when your Azure deployment name matches GPT-image-1" description: "Use when your Azure deployment name matches GPT-image-1"
``` ```
@@ -23,8 +23,8 @@ default_image_api_dialect: null # openai-native|ratio-metadata|null (OpenAI-com
default_model: default_model:
google: null # e.g., "gemini-3-pro-image-preview", "gemini-3.1-flash-image-preview" google: null # e.g., "gemini-3-pro-image-preview", "gemini-3.1-flash-image-preview"
openai: null # e.g., "gpt-image-1.5", "gpt-image-1" openai: null # e.g., "gpt-image-2", "gpt-image-1.5", "gpt-image-1"
azure: null # Azure deployment name, e.g., "gpt-image-1.5" or "image-prod" azure: null # Azure deployment name, e.g., "gpt-image-2" or "image-prod"
openrouter: null # e.g., "google/gemini-3.1-flash-image-preview" openrouter: null # e.g., "google/gemini-3.1-flash-image-preview"
dashscope: null # e.g., "qwen-image-2.0-pro" dashscope: null # e.g., "qwen-image-2.0-pro"
zai: null # e.g., "glm-image" zai: null # e.g., "glm-image"
@@ -106,8 +106,8 @@ default_image_size: 2K
default_image_api_dialect: null default_image_api_dialect: null
default_model: default_model:
google: "gemini-3-pro-image-preview" google: "gemini-3-pro-image-preview"
openai: "gpt-image-1.5" openai: "gpt-image-2"
azure: "gpt-image-1.5" azure: "gpt-image-2"
openrouter: "google/gemini-3.1-flash-image-preview" openrouter: "google/gemini-3.1-flash-image-preview"
dashscope: "qwen-image-2.0-pro" dashscope: "qwen-image-2.0-pro"
zai: "glm-image" zai: "glm-image"
@@ -25,10 +25,13 @@ ${BUN_X} {baseDir}/scripts/main.ts --prompt "Make blue" --image out.png --ref so
```bash ```bash
# OpenAI # OpenAI
${BUN_X} {baseDir}/scripts/main.ts --prompt "A cat" --image out.png --provider openai ${BUN_X} {baseDir}/scripts/main.ts --prompt "A cat" --image out.png --provider openai --model gpt-image-2
# Azure OpenAI (model = deployment name) # Azure OpenAI (model = deployment name)
${BUN_X} {baseDir}/scripts/main.ts --prompt "A cat" --image out.png --provider azure --model gpt-image-1.5 ${BUN_X} {baseDir}/scripts/main.ts --prompt "A cat" --image out.png --provider azure --model gpt-image-2
# OpenAI GPT Image 2 custom 4K size
${BUN_X} {baseDir}/scripts/main.ts --prompt "A cinematic landscape" --image out.png --provider openai --model gpt-image-2 --size 3840x2160
# Google with explicit model # Google with explicit model
${BUN_X} {baseDir}/scripts/main.ts --prompt "Make blue" --image out.png --provider google --model gemini-3-pro-image-preview --ref source.png ${BUN_X} {baseDir}/scripts/main.ts --prompt "Make blue" --image out.png --provider google --model gemini-3-pro-image-preview --ref source.png
+2 -2
View File
@@ -133,7 +133,7 @@ default_image_size: 2K
default_image_api_dialect: ratio-metadata default_image_api_dialect: ratio-metadata
default_model: default_model:
google: gemini-3-pro-image-preview google: gemini-3-pro-image-preview
openai: gpt-image-1.5 openai: gpt-image-2
zai: glm-image zai: glm-image
azure: image-prod azure: image-prod
minimax: image-01 minimax: image-01
@@ -165,7 +165,7 @@ batch:
assert.equal(config.default_image_size, "2K"); assert.equal(config.default_image_size, "2K");
assert.equal(config.default_image_api_dialect, "ratio-metadata"); assert.equal(config.default_image_api_dialect, "ratio-metadata");
assert.equal(config.default_model?.google, "gemini-3-pro-image-preview"); assert.equal(config.default_model?.google, "gemini-3-pro-image-preview");
assert.equal(config.default_model?.openai, "gpt-image-1.5"); assert.equal(config.default_model?.openai, "gpt-image-2");
assert.equal(config.default_model?.zai, "glm-image"); assert.equal(config.default_model?.zai, "glm-image");
assert.equal(config.default_model?.azure, "image-prod"); assert.equal(config.default_model?.azure, "image-prod");
assert.equal(config.default_model?.minimax, "image-01"); assert.equal(config.default_model?.minimax, "image-01");
+2 -2
View File
@@ -124,7 +124,7 @@ Environment variables:
JIMENG_ACCESS_KEY_ID Jimeng Access Key ID JIMENG_ACCESS_KEY_ID Jimeng Access Key ID
JIMENG_SECRET_ACCESS_KEY Jimeng Secret Access Key JIMENG_SECRET_ACCESS_KEY Jimeng Secret Access Key
ARK_API_KEY Seedream/Ark API key ARK_API_KEY Seedream/Ark API key
OPENAI_IMAGE_MODEL Default OpenAI model (gpt-image-1.5) OPENAI_IMAGE_MODEL Default OpenAI model (gpt-image-2)
OPENROUTER_IMAGE_MODEL Default OpenRouter model (google/gemini-3.1-flash-image-preview) OPENROUTER_IMAGE_MODEL Default OpenRouter model (google/gemini-3.1-flash-image-preview)
GOOGLE_IMAGE_MODEL Default Google model (gemini-3-pro-image-preview) GOOGLE_IMAGE_MODEL Default Google model (gemini-3-pro-image-preview)
DASHSCOPE_IMAGE_MODEL Default DashScope model (qwen-image-2.0-pro) DASHSCOPE_IMAGE_MODEL Default DashScope model (qwen-image-2.0-pro)
@@ -151,7 +151,7 @@ Environment variables:
AZURE_OPENAI_BASE_URL Azure OpenAI resource or deployment endpoint AZURE_OPENAI_BASE_URL Azure OpenAI resource or deployment endpoint
AZURE_OPENAI_DEPLOYMENT Default Azure deployment name AZURE_OPENAI_DEPLOYMENT Default Azure deployment name
AZURE_API_VERSION Azure API version (default: 2025-04-01-preview) AZURE_API_VERSION Azure API version (default: 2025-04-01-preview)
AZURE_OPENAI_IMAGE_MODEL Backward-compatible Azure deployment/model alias (defaults to gpt-image-1.5) AZURE_OPENAI_IMAGE_MODEL Backward-compatible Azure deployment/model alias (defaults to gpt-image-2)
SEEDREAM_BASE_URL Custom Seedream endpoint SEEDREAM_BASE_URL Custom Seedream endpoint
BAOYU_IMAGE_GEN_MAX_WORKERS Override batch worker cap BAOYU_IMAGE_GEN_MAX_WORKERS Override batch worker cap
BAOYU_IMAGE_GEN_<PROVIDER>_CONCURRENCY Override provider concurrency BAOYU_IMAGE_GEN_<PROVIDER>_CONCURRENCY Override provider concurrency
@@ -46,7 +46,7 @@ export function getDefaultModel(): string {
} }
} }
return process.env.AZURE_OPENAI_IMAGE_MODEL || "gpt-image-1.5"; return process.env.AZURE_OPENAI_IMAGE_MODEL || "gpt-image-2";
} }
function getEndpoint(): AzureEndpoint { function getEndpoint(): AzureEndpoint {
@@ -1,9 +1,11 @@
import assert from "node:assert/strict"; import assert from "node:assert/strict";
import test from "node:test"; import test from "node:test";
import type { CliArgs } from "../types.ts";
import { import {
buildOpenAIGenerationsBody, buildOpenAIGenerationsBody,
extractImageFromResponse, extractImageFromResponse,
getDefaultModel,
getOpenAIAspectRatio, getOpenAIAspectRatio,
getOpenAIImageApiDialect, getOpenAIImageApiDialect,
getOpenAIResolution, getOpenAIResolution,
@@ -13,9 +15,33 @@ import {
inferAspectRatioFromSize, inferAspectRatioFromSize,
inferResolutionFromSize, inferResolutionFromSize,
parseAspectRatio, parseAspectRatio,
validateArgs,
} from "./openai.ts"; } from "./openai.ts";
function makeArgs(overrides: Partial<CliArgs> = {}): CliArgs {
return {
prompt: null,
promptFiles: [],
imagePath: null,
provider: null,
model: null,
aspectRatio: null,
size: null,
quality: "2k",
imageSize: null,
imageApiDialect: null,
referenceImages: [],
n: 1,
batchFile: null,
jobs: null,
json: false,
help: false,
...overrides,
};
}
test("OpenAI aspect-ratio parsing and size selection match model families", () => { test("OpenAI aspect-ratio parsing and size selection match model families", () => {
assert.equal(getDefaultModel(), "gpt-image-2");
assert.deepEqual(parseAspectRatio("16:9"), { width: 16, height: 9 }); assert.deepEqual(parseAspectRatio("16:9"), { width: 16, height: 9 });
assert.equal(parseAspectRatio("wide"), null); assert.equal(parseAspectRatio("wide"), null);
assert.equal(parseAspectRatio("0:1"), null); assert.equal(parseAspectRatio("0:1"), null);
@@ -25,6 +51,10 @@ test("OpenAI aspect-ratio parsing and size selection match model families", () =
assert.equal(getOpenAISize("dall-e-2", "16:9", "2k"), "1024x1024"); assert.equal(getOpenAISize("dall-e-2", "16:9", "2k"), "1024x1024");
assert.equal(getOpenAISize("gpt-image-1.5", "16:9", "2k"), "1536x1024"); assert.equal(getOpenAISize("gpt-image-1.5", "16:9", "2k"), "1536x1024");
assert.equal(getOpenAISize("gpt-image-1.5", "4:3", "2k"), "1024x1024"); assert.equal(getOpenAISize("gpt-image-1.5", "4:3", "2k"), "1024x1024");
assert.equal(getOpenAISize("gpt-image-2", "16:9", "2k"), "2048x1152");
assert.equal(getOpenAISize("gpt-image-2", "9:16", "2k"), "1152x2048");
assert.equal(getOpenAISize("gpt-image-2", "4:3", "2k"), "2048x1536");
assert.equal(getOpenAISize("gpt-image-2", "2.35:1", "normal"), "1248x528");
assert.equal(inferAspectRatioFromSize("1536x1024"), "3:2"); assert.equal(inferAspectRatioFromSize("1536x1024"), "3:2");
assert.equal(inferResolutionFromSize("1536x1024"), "2K"); assert.equal(inferResolutionFromSize("1536x1024"), "2K");
assert.equal(getOpenAIAspectRatio({ aspectRatio: null, size: "2048x1152" }), "16:9"); assert.equal(getOpenAIAspectRatio({ aspectRatio: null, size: "2048x1152" }), "16:9");
@@ -37,7 +67,7 @@ test("OpenAI aspect-ratio parsing and size selection match model families", () =
test("OpenAI generations body switches between native and ratio-metadata dialects", () => { test("OpenAI generations body switches between native and ratio-metadata dialects", () => {
assert.deepEqual( assert.deepEqual(
buildOpenAIGenerationsBody("Draw a skyline", "gpt-image-1.5", { buildOpenAIGenerationsBody("Draw a skyline", "gpt-image-2", {
aspectRatio: "16:9", aspectRatio: "16:9",
size: null, size: null,
quality: "2k", quality: "2k",
@@ -45,9 +75,10 @@ test("OpenAI generations body switches between native and ratio-metadata dialect
imageApiDialect: null, imageApiDialect: null,
}), }),
{ {
model: "gpt-image-1.5", model: "gpt-image-2",
prompt: "Draw a skyline", prompt: "Draw a skyline",
size: "1536x1024", size: "2048x1152",
quality: "high",
}, },
); );
@@ -90,6 +121,28 @@ test("OpenAI generations body switches between native and ratio-metadata dialect
); );
}); });
test("OpenAI validates gpt-image-2 custom size constraints", () => {
assert.doesNotThrow(() =>
validateArgs("gpt-image-2", makeArgs({ size: "3840x2160" })),
);
assert.doesNotThrow(() =>
validateArgs("gpt-image-2-2026-04-21", makeArgs({ aspectRatio: "2.35:1" })),
);
assert.throws(
() => validateArgs("gpt-image-2", makeArgs({ size: "1024x576" })),
/total pixels/,
);
assert.throws(
() => validateArgs("gpt-image-2", makeArgs({ size: "1025x1024" })),
/multiples of 16px/,
);
assert.throws(
() => validateArgs("gpt-image-2", makeArgs({ aspectRatio: "4:1" })),
/must not exceed 3:1/,
);
});
test("OpenAI mime-type detection covers supported reference image extensions", () => { test("OpenAI mime-type detection covers supported reference image extensions", () => {
assert.equal(getMimeType("frame.png"), "image/png"); assert.equal(getMimeType("frame.png"), "image/png");
assert.equal(getMimeType("frame.jpg"), "image/jpeg"); assert.equal(getMimeType("frame.jpg"), "image/jpeg");
@@ -3,7 +3,7 @@ import { readFile } from "node:fs/promises";
import type { CliArgs, OpenAIImageApiDialect } from "../types"; import type { CliArgs, OpenAIImageApiDialect } from "../types";
export function getDefaultModel(): string { export function getDefaultModel(): string {
return process.env.OPENAI_IMAGE_MODEL || "gpt-image-1.5"; return process.env.OPENAI_IMAGE_MODEL || "gpt-image-2";
} }
type OpenAIImageResponse = { data: Array<{ url?: string; b64_json?: string }> }; type OpenAIImageResponse = { data: Array<{ url?: string; b64_json?: string }> };
@@ -25,6 +25,55 @@ type SizeMapping = {
type OpenAIGenerationsBody = Record<string, unknown>; type OpenAIGenerationsBody = Record<string, unknown>;
function isGptImageModel(model: string): boolean {
return model.includes("gpt-image");
}
function isGptImage2Model(model: string): boolean {
return model.includes("gpt-image-2");
}
function roundToMultiple(value: number, multiple: number): number {
return Math.max(multiple, Math.round(value / multiple) * multiple);
}
function buildGptImage2SizeFromAspectRatio(
ar: string | null,
quality: CliArgs["quality"],
): string {
const parsed = ar ? parseAspectRatio(ar) : null;
const ratio = parsed ? parsed.width / parsed.height : 1;
if (!parsed || Math.abs(ratio - 1) < 0.1) {
const edge = quality === "2k" ? 2048 : 1024;
return `${edge}x${edge}`;
}
const targetLongEdge = quality === "2k" ? 2048 : 1024;
let width: number;
let height: number;
if (ratio > 1) {
width = targetLongEdge;
height = roundToMultiple(width / ratio, 16);
} else {
height = targetLongEdge;
width = roundToMultiple(height * ratio, 16);
}
while (width * height < 655_360) {
if (ratio > 1) {
width += 16;
height = roundToMultiple(width / ratio, 16);
} else {
height += 16;
width = roundToMultiple(height * ratio, 16);
}
}
return `${width}x${height}`;
}
export function getOpenAISize( export function getOpenAISize(
model: string, model: string,
ar: string | null, ar: string | null,
@@ -37,6 +86,10 @@ export function getOpenAISize(
return "1024x1024"; return "1024x1024";
} }
if (isGptImage2Model(model)) {
return buildGptImage2SizeFromAspectRatio(ar, quality);
}
const sizes: SizeMapping = isDalle3 const sizes: SizeMapping = isDalle3
? { ? {
square: "1024x1024", square: "1024x1024",
@@ -127,6 +180,18 @@ export function getOpenAIResolution(
return args.quality === "normal" ? "1K" : "2K"; return args.quality === "normal" ? "1K" : "2K";
} }
function getOpenAIQuality(model: string, quality: CliArgs["quality"]): "standard" | "hd" | "medium" | "high" | null {
if (model.includes("dall-e-3")) {
return quality === "2k" ? "hd" : "standard";
}
if (isGptImageModel(model)) {
return quality === "2k" ? "high" : "medium";
}
return null;
}
export function getOrientationFromAspectRatio(ar: string): "landscape" | "portrait" | null { export function getOrientationFromAspectRatio(ar: string): "landscape" | "portrait" | null {
const parsed = parseAspectRatio(ar); const parsed = parseAspectRatio(ar);
if (!parsed) return null; if (!parsed) return null;
@@ -163,13 +228,53 @@ export function buildOpenAIGenerationsBody(
size: args.size || getOpenAISize(model, args.aspectRatio, args.quality), size: args.size || getOpenAISize(model, args.aspectRatio, args.quality),
}; };
if (model.includes("dall-e-3")) { const quality = getOpenAIQuality(model, args.quality);
body.quality = args.quality === "2k" ? "hd" : "standard"; if (quality) {
body.quality = quality;
} }
return body; return body;
} }
export function validateArgs(model: string, args: CliArgs): void {
if (!isGptImage2Model(model)) return;
if (args.aspectRatio && !args.size) {
const parsed = parseAspectRatio(args.aspectRatio);
if (!parsed) {
throw new Error(`Invalid gpt-image-2 aspect ratio: ${args.aspectRatio}`);
}
const ratio = parsed.width / parsed.height;
if (Math.max(ratio, 1 / ratio) > 3) {
throw new Error("gpt-image-2 aspect ratio must not exceed 3:1.");
}
}
if (!args.size) return;
const parsedSize = parsePixelSize(args.size);
if (!parsedSize) {
throw new Error(`Invalid gpt-image-2 --size: ${args.size}. Expected <width>x<height>.`);
}
const { width, height } = parsedSize;
const totalPixels = width * height;
const ratio = Math.max(width, height) / Math.min(width, height);
if (Math.max(width, height) > 3840) {
throw new Error("gpt-image-2 --size maximum edge length must be 3840px or less.");
}
if (width % 16 !== 0 || height % 16 !== 0) {
throw new Error("gpt-image-2 --size width and height must both be multiples of 16px.");
}
if (ratio > 3) {
throw new Error("gpt-image-2 --size long edge to short edge ratio must not exceed 3:1.");
}
if (totalPixels < 655_360 || totalPixels > 8_294_400) {
throw new Error("gpt-image-2 --size total pixels must be between 655,360 and 8,294,400.");
}
}
export async function generateImage( export async function generateImage(
prompt: string, prompt: string,
model: string, model: string,
@@ -198,7 +303,7 @@ export async function generateImage(
} }
if (model.includes("dall-e-2") || model.includes("dall-e-3")) { if (model.includes("dall-e-2") || model.includes("dall-e-3")) {
throw new Error( throw new Error(
"Reference images with OpenAI in this skill require GPT Image models. Use --model gpt-image-1.5 (or another gpt-image model)." "Reference images with OpenAI in this skill require GPT Image models. Use --model gpt-image-2 (or another gpt-image model)."
); );
} }
const size = args.size || getOpenAISize(model, args.aspectRatio, args.quality); const size = args.size || getOpenAISize(model, args.aspectRatio, args.quality);
@@ -283,8 +388,9 @@ async function generateWithOpenAIEdits(
form.append("prompt", prompt); form.append("prompt", prompt);
form.append("size", size); form.append("size", size);
if (model.includes("gpt-image")) { const openAIQuality = getOpenAIQuality(model, quality);
form.append("quality", quality === "2k" ? "high" : "medium"); if (openAIQuality && openAIQuality !== "standard" && openAIQuality !== "hd") {
form.append("quality", openAIQuality);
} }
for (const refPath of referenceImages) { for (const refPath of referenceImages) {
+26 -10
View File
@@ -1,7 +1,7 @@
--- ---
name: baoyu-infographic name: baoyu-infographic
description: Generate professional infographics with 21 layout types and 21 visual styles. Analyzes content, recommends layout×style combinations, and generates publication-ready infographics. Use when user asks to create "infographic", "信息图", "visual summary", "可视化", or "高密度信息大图". description: Generate professional infographics with 21 layout types and 21 visual styles. Analyzes content, recommends layout×style combinations, and generates publication-ready infographics. Use when user asks to create "infographic", "信息图", "visual summary", "可视化", or "高密度信息大图".
version: 1.56.1 version: 1.57.0
metadata: metadata:
openclaw: openclaw:
homepage: https://github.com/JimLiu/baoyu-skills#baoyu-infographic homepage: https://github.com/JimLiu/baoyu-skills#baoyu-infographic
@@ -23,11 +23,17 @@ Concrete `AskUserQuestion` references below are examples — substitute the loca
## Image Generation Tools ## Image Generation Tools
When this skill needs to render an image: When this skill needs to render an image, resolve the backend in this order:
- **Use whatever image-generation tool or skill is available** in the current runtime — e.g., Codex `imagegen`, Hermes `image_generate`, `baoyu-imagine`, or any equivalent the user has installed. 1. **Current-request override** if the user names a specific backend in the current message, use it.
- **If multiple are available**, ask the user **once** at the start which to use (batch with any other initial questions). 2. **Saved preference** — if `EXTEND.md` sets `preferred_image_backend` to a backend available right now, use it.
- **If none are available**, tell the user and ask how to proceed. 3. **Auto-select** (when the preference is `auto`, unset, or the pinned backend isn't available):
- If the current runtime exposes a native image tool (e.g., Codex `imagegen`, Hermes `image_generate`), use it. Runtime-native tools are preferred by default — agents that know their own tool inventory should surface the native one here.
- Otherwise, if exactly one non-native backend is installed (e.g., `baoyu-imagine`), use it.
- Otherwise (multiple non-native backends with no runtime-native tool), ask the user once — batch with any other initial questions.
4. **If none are available**, tell the user and ask how to proceed.
Setting `preferred_image_backend: ask` forces the step-3 prompt every run regardless of available backends. Users change the pinned backend via the `## Changing Preferences` section below.
**Prompt file requirement (hard)**: write each image's full, final prompt to a standalone file under `prompts/` (naming: `NN-{type}-[slug].md`) BEFORE invoking any backend. The backend receives the prompt file (or its content); the file is the reproducibility record and lets you switch backends without regenerating prompts. **Prompt file requirement (hard)**: write each image's full, final prompt to a standalone file under `prompts/` (naming: `NN-{type}-[slug].md`) BEFORE invoking any backend. The backend receives the prompt file (or its content); the file is the reproducibility record and lets you switch backends without regenerating prompts.
@@ -201,7 +207,7 @@ Check EXTEND.md in priority order — the first one found wins:
| Found | Read, parse, display a one-line summary | | Found | Read, parse, display a one-line summary |
| Not found | Ask the user with `AskUserQuestion` (see `references/config/first-time-setup.md`) | | Not found | Ask the user with `AskUserQuestion` (see `references/config/first-time-setup.md`) |
**EXTEND.md supports**: preferred layout/style, default aspect ratio, custom style definitions, language preference. **EXTEND.md supports**: preferred layout/style, default aspect ratio, language preference, preferred image backend, custom style definitions.
Schema: `references/config/preferences-schema.md` Schema: `references/config/preferences-schema.md`
@@ -248,6 +254,7 @@ Ask the user to confirm the questions below following the [User Input Tools](#us
| 1 | **Combination** | Always | 3+ layout×style combos with rationale | | 1 | **Combination** | Always | 3+ layout×style combos with rationale |
| 2 | **Aspect** | Always | Named presets (landscape/portrait/square) or custom W:H ratio (e.g., 3:4, 4:3, 2.35:1) | | 2 | **Aspect** | Always | Named presets (landscape/portrait/square) or custom W:H ratio (e.g., 3:4, 4:3, 2.35:1) |
| 3 | **Language** | Only if source ≠ user language | Language for text content | | 3 | **Language** | Only if source ≠ user language | Language for text content |
| 4 | **Image Backend** | Only if step 3 of the `## Image Generation Tools` rule needs to ask (no runtime-native tool AND multiple non-native backends, OR `preferred_image_backend: ask`) | Available backends |
### Step 5: Generate Prompt → `prompts/infographic.md` ### Step 5: Generate Prompt → `prompts/infographic.md`
@@ -266,7 +273,7 @@ Combine:
### Step 6: Generate Image ### Step 6: Generate Image
1. Select the backend via the `## Image Generation Tools` rule at the top: use whatever is available; if multiple, ask the user once. Do this once per session. 1. Resolve the backend per the `## Image Generation Tools` rule at the top of this file.
2. Ensure the full final prompt is persisted at `prompts/infographic.md` (already written in Step 5) BEFORE invoking the backend — the file is the reproducibility record. 2. Ensure the full final prompt is persisted at `prompts/infographic.md` (already written in Step 5) BEFORE invoking the backend — the file is the reproducibility record.
3. **Check for existing file**: Before generating, check if `infographic.png` exists 3. **Check for existing file**: Before generating, check if `infographic.png` exists
- If exists: Rename to `infographic-backup-YYYYMMDD-HHMMSS.png` - If exists: Rename to `infographic-backup-YYYYMMDD-HHMMSS.png`
@@ -275,7 +282,7 @@ Combine:
### Step 7: Output Summary ### Step 7: Output Summary
Report: topic, layout, style, aspect, language, output path, files created. Report: topic, layout, style, aspect, language, image backend, output path, files created.
## References ## References
@@ -285,6 +292,15 @@ Report: topic, layout, style, aspect, language, output path, files created.
- `references/layouts/<layout>.md` - 21 layout definitions - `references/layouts/<layout>.md` - 21 layout definitions
- `references/styles/<style>.md` - 21 style definitions - `references/styles/<style>.md` - 21 style definitions
## Extension Support ## Changing Preferences
Custom configurations via EXTEND.md. See **Step 1.1** for paths and supported options. EXTEND.md lives at the first matching path in Step 1.1. Three ways to change it:
- **Edit directly** — open EXTEND.md and change fields. Full schema: `references/config/preferences-schema.md`.
- **Reconfigure interactively** — delete EXTEND.md (or ask "reconfigure baoyu-infographic preferences" / "重新配置"). The next run re-triggers first-time setup.
- **Common one-line edits**:
- `preferred_image_backend: auto` — default; runtime-native tool wins, falls back to the only installed backend, asks only if multiple non-native are present.
- `preferred_image_backend: codex-imagegen` — pin to Codex's built-in.
- `preferred_image_backend: baoyu-imagine` — pin to the baoyu-imagine skill.
- `preferred_image_backend: ask` — confirm backend every run.
- `preferred_layout: dense-modules`, `preferred_style: morandi-journal`, `preferred_aspect: portrait`, `language: zh` — shift the Step-3 recommendations and Step-4 defaults.
@@ -141,13 +141,13 @@ preferred_layout: [selected layout or null]
preferred_style: [selected style or null] preferred_style: [selected style or null]
preferred_aspect: [landscape|portrait|square|null] preferred_aspect: [landscape|portrait|square|null]
language: [selected language or null] language: [selected language or null]
preferred_image_backend: auto
custom_styles: [] custom_styles: []
--- ---
``` ```
`preferred_image_backend: auto` is the baked-in default — first-time setup never asks about it. The `## Image Generation Tools` rule in SKILL.md then picks the runtime-native tool (Codex `imagegen`, Hermes `image_generate`, etc.) when one is available, and falls back to installed backends like `baoyu-imagine`.
## Modifying Preferences Later ## Modifying Preferences Later
Users can edit EXTEND.md directly or trigger setup again: See the `## Changing Preferences` section in `SKILL.md` for the canonical list of common edits (pin backend, change layout/style defaults, retrigger setup). Full schema: `references/config/preferences-schema.md`.
- Delete EXTEND.md to re-trigger setup
- Edit YAML frontmatter for quick changes
- Full schema: `references/config/preferences-schema.md`
@@ -17,6 +17,8 @@ preferred_aspect: null # landscape|portrait|square|null (custom W:H also acc
language: null # zh|en|ja|ko|null (null = auto-detect from source) language: null # zh|en|ja|ko|null (null = auto-detect from source)
preferred_image_backend: auto # auto|ask|<backend-id>
custom_styles: # extra style definitions merged with the 21 built-ins custom_styles: # extra style definitions merged with the 21 built-ins
- name: my-brand - name: my-brand
description: "Short description shown in Step 3 recommendations" description: "Short description shown in Step 3 recommendations"
@@ -33,8 +35,19 @@ custom_styles: # extra style definitions merged with the 21 built-ins
| `preferred_style` | string\|null | null | Pre-selected style — surfaces as the top recommendation in Step 3 | | `preferred_style` | string\|null | null | Pre-selected style — surfaces as the top recommendation in Step 3 |
| `preferred_aspect` | string\|null | null | Default aspect for Step 4 (named preset or W:H string) | | `preferred_aspect` | string\|null | null | Default aspect for Step 4 (named preset or W:H string) |
| `language` | string\|null | null | Output language (null = auto-detect from source content) | | `language` | string\|null | null | Output language (null = auto-detect from source content) |
| `preferred_image_backend` | string | `auto` | Image backend selection. `auto` = prefer runtime-native tool, fall back to the only installed backend, ask if multiple non-native are present. `ask` = always confirm on every run. `<backend-id>` (e.g., `codex-imagegen`, `baoyu-imagine`, `image_generate`) = pin this backend when available; fall back to `auto` when it isn't. Absent = `auto`. |
| `custom_styles` | array | [] | Additional styles available alongside the 21 built-ins | | `custom_styles` | array | [] | Additional styles available alongside the 21 built-ins |
Backend resolution logic is documented in the `## Image Generation Tools` section of `SKILL.md`. This doc only defines the field.
Example backend ids:
| Value | Meaning |
|-------|---------|
| `codex-imagegen` | Codex built-in `imagegen` tool |
| `baoyu-imagine` | `baoyu-imagine` skill / script backend |
| `image_generate` | Generic runtime image tool such as Hermes |
## Layout Options ## Layout Options
See the **Layout Gallery (21)** table in `SKILL.md` for the canonical list. Common picks: See the **Layout Gallery (21)** table in `SKILL.md` for the canonical list. Common picks:
@@ -87,6 +100,8 @@ language: zh
--- ---
``` ```
`preferred_image_backend` is omitted above; absence is treated as `auto`.
## Example: Full Preferences ## Example: Full Preferences
```yaml ```yaml
@@ -99,6 +114,8 @@ preferred_aspect: portrait
language: zh language: zh
preferred_image_backend: codex-imagegen
custom_styles: custom_styles:
- name: my-brand - name: my-brand
description: "Brand-aligned warm pastel infographic" description: "Brand-aligned warm pastel infographic"
+23 -5
View File
@@ -27,14 +27,22 @@ Concrete `AskUserQuestion` references below are examples — substitute the loca
## Image Generation Tools ## Image Generation Tools
When this skill needs to render an image: When this skill needs to render an image, resolve the backend in this order:
- **Use whatever image-generation tool or skill is available** in the current runtime — e.g., Codex `imagegen`, Hermes `image_generate`, `baoyu-imagine`, or any equivalent the user has installed. 1. **Current-request override** if the user names a specific backend in the current message, use it.
- **If multiple are available**, ask the user **once** at the start which to use (batch with any other initial questions). 2. **Saved preference** — if `EXTEND.md` sets `preferred_image_backend` to a backend available right now, use it.
- **If none are available**, tell the user and ask how to proceed. 3. **Auto-select** (when the preference is `auto`, unset, or the pinned backend isn't available):
- If the current runtime exposes a native image tool (e.g., Codex `imagegen`, Hermes `image_generate`), use it. Runtime-native tools are preferred by default — agents that know their own tool inventory should surface the native one here.
- Otherwise, if exactly one non-native backend is installed (e.g., `baoyu-imagine`), use it.
- Otherwise (multiple non-native backends with no runtime-native tool), ask the user once — batch with any other initial questions.
4. **If none are available**, tell the user and ask how to proceed.
Setting `preferred_image_backend: ask` forces the step-3 prompt every run regardless of available backends. Users change the pinned backend via the `## Changing Preferences` section below.
**Prompt file requirement (hard)**: write each image's full, final prompt to a standalone file under `prompts/` (naming: `NN-slide-[slug].md`) BEFORE invoking any backend. The file is the reproducibility record and lets you switch backends without regenerating prompts. **Prompt file requirement (hard)**: write each image's full, final prompt to a standalone file under `prompts/` (naming: `NN-slide-[slug].md`) BEFORE invoking any backend. The file is the reproducibility record and lets you switch backends without regenerating prompts.
Concrete tool names (`imagegen`, `image_generate`, `baoyu-imagine`) above are examples — substitute the local equivalents under the same rule.
## Language ## Language
Respond in the user's language across questions, progress reports, error messages, and the completion summary. Keep technical tokens (style names, file paths, code) in English. Respond in the user's language across questions, progress reports, error messages, and the completion summary. Keep technical tokens (style names, file paths, code) in English.
@@ -320,4 +328,14 @@ See `references/modification-guide.md` for full details.
- For sensitive public figures, prefer stylized alternatives to avoid likeness issues. - For sensitive public figures, prefer stylized alternatives to avoid likeness issues.
- Maintain visual consistency via the session ID when the backend supports it. - Maintain visual consistency via the session ID when the backend supports it.
Custom configurations via EXTEND.md. See Step 1.1 for paths and schema. ## Changing Preferences
EXTEND.md lives at the first matching path listed in Step 1.1. Two ways to change it:
- **Edit directly** — open EXTEND.md and change fields. Full schema: `references/config/preferences-schema.md`.
- **Common one-line edits**:
- `preferred_image_backend: auto` — default; runtime-native tool wins, falls back to the only installed backend, asks only if multiple non-native are present.
- `preferred_image_backend: codex-imagegen` — pin to Codex's built-in.
- `preferred_image_backend: baoyu-imagine` — pin to the baoyu-imagine skill.
- `preferred_image_backend: ask` — confirm backend every run.
- `preferred_style: blueprint`, `preferred_audience: experts`, `language: zh`.
@@ -12,6 +12,7 @@ style: blueprint # Preset name OR "custom"
audience: general # beginners | intermediate | experts | executives | general audience: general # beginners | intermediate | experts | executives | general
language: auto # auto | en | zh | ja | etc. language: auto # auto | en | zh | ja | etc.
review: true # true = review outline before generation review: true # true = review outline before generation
preferred_image_backend: auto # auto | ask | <backend-id>
## Custom Dimensions (only when style: custom) ## Custom Dimensions (only when style: custom)
dimensions: dimensions:
@@ -40,6 +41,7 @@ custom_styles:
| `audience` | string | `general` | Default target audience | | `audience` | string | `general` | Default target audience |
| `language` | string | `auto` | Output language (auto = detect from input) | | `language` | string | `auto` | Output language (auto = detect from input) |
| `review` | boolean | `true` | Show outline review before generation | | `review` | boolean | `true` | Show outline review before generation |
| `preferred_image_backend` | string | `auto` | Image backend selection. `auto` = prefer runtime-native tool, fall back to the only installed backend, ask if multiple non-native are present. `ask` = always confirm on every run. `<backend-id>` (e.g., `codex-imagegen`, `baoyu-imagine`, `image_generate`) = pin this backend when available; fall back to `auto` when it isn't. Absent = `auto`. Resolution logic is documented in `SKILL.md`'s `## Image Generation Tools` section. |
### Custom Dimensions ### Custom Dimensions
+25 -5
View File
@@ -24,14 +24,22 @@ Concrete `AskUserQuestion` references below are examples — substitute the loca
## Image Generation Tools ## Image Generation Tools
When this skill needs to render an image: When this skill needs to render an image, resolve the backend in this order:
- **Use whatever image-generation tool or skill is available** in the current runtime — e.g., Codex `imagegen`, Hermes `image_generate`, `baoyu-imagine`, or any equivalent the user has installed. 1. **Current-request override** if the user names a specific backend in the current message, use it.
- **If multiple are available**, ask the user **once** at the start which to use (batch with any other initial questions). 2. **Saved preference** — if `EXTEND.md` sets `preferred_image_backend` to a backend available right now, use it.
- **If none are available**, tell the user and ask how to proceed. 3. **Auto-select** (when the preference is `auto`, unset, or the pinned backend isn't available):
- If the current runtime exposes a native image tool (e.g., Codex `imagegen`, Hermes `image_generate`), use it. Runtime-native tools are preferred by default — agents that know their own tool inventory should surface the native one here.
- Otherwise, if exactly one non-native backend is installed (e.g., `baoyu-imagine`), use it.
- Otherwise (multiple non-native backends with no runtime-native tool), ask the user once — batch with any other initial questions.
4. **If none are available**, tell the user and ask how to proceed.
Setting `preferred_image_backend: ask` forces the step-3 prompt every run regardless of available backends. Users change the pinned backend via the `## Changing Preferences` section below.
**Prompt file requirement (hard)**: write each image's full, final prompt to a standalone file under `prompts/` (naming: `NN-{type}-[slug].md`) BEFORE invoking any backend. The file is the reproducibility record and lets you switch backends without regenerating prompts. **Prompt file requirement (hard)**: write each image's full, final prompt to a standalone file under `prompts/` (naming: `NN-{type}-[slug].md`) BEFORE invoking any backend. The file is the reproducibility record and lets you switch backends without regenerating prompts.
Concrete tool names (`imagegen`, `image_generate`, `baoyu-imagine`) above are examples — substitute the local equivalents under the same rule.
## Language ## Language
Respond in the user's language across questions, progress, errors, and completion summary. Keep technical tokens (style names, file paths, code) in English. Respond in the user's language across questions, progress, errors, and completion summary. Keep technical tokens (style names, file paths, code) in English.
@@ -418,4 +426,16 @@ Always update the prompt file before regenerating — it's the source of truth a
- For sensitive public figures, use stylized cartoon alternatives. - For sensitive public figures, use stylized cartoon alternatives.
- Smart Confirm (Step 2) is required; Detailed mode adds a second confirmation (2a + 2c). - Smart Confirm (Step 2) is required; Detailed mode adds a second confirmation (2a + 2c).
Custom configurations via EXTEND.md. See Step 0 for paths and schema. ## Changing Preferences
EXTEND.md lives at the first matching path listed in Step 0. Three ways to change it:
- **Edit directly** — open EXTEND.md and change fields. Full schema: `references/config/preferences-schema.md`.
- **Reconfigure interactively** — delete EXTEND.md (or ask "reconfigure baoyu-xhs-images preferences" / "重新配置"). The next run re-triggers first-time setup.
- **Common one-line edits**:
- `preferred_image_backend: auto` — default; runtime-native tool wins, falls back to the only installed backend, asks only if multiple non-native are present.
- `preferred_image_backend: codex-imagegen` — pin to Codex's built-in.
- `preferred_image_backend: baoyu-imagine` — pin to the baoyu-imagine skill.
- `preferred_image_backend: ask` — confirm backend every run.
- `preferred_style: notion`, `preferred_layout: dense`, `preferred_palette: macaron`, `language: zh`.
- `watermark.enabled: true` + `watermark.content: "@handle"` — add a watermark.
@@ -110,13 +110,13 @@ preferred_style:
description: "" description: ""
preferred_layout: null preferred_layout: null
language: null language: null
preferred_image_backend: auto
custom_styles: [] custom_styles: []
--- ---
``` ```
`preferred_image_backend: auto` is the baked-in default — first-time setup does not ask about it. The `## Image Generation Tools` rule in SKILL.md then picks the runtime-native tool (Codex `imagegen`, Hermes `image_generate`, etc.) when available, and falls back to installed backends.
## Modifying Preferences Later ## Modifying Preferences Later
Users can edit EXTEND.md directly or run setup again: See the `## Changing Preferences` section in `SKILL.md` for the canonical list of common edits (pin backend, change defaults, retrigger setup). Full schema: `preferences-schema.md`.
- Delete EXTEND.md to trigger setup
- Edit YAML frontmatter for quick changes
- Full schema: `config/preferences-schema.md`
@@ -24,6 +24,8 @@ preferred_layout: null # sparse|balanced|dense|list|comparison|flow
language: null # zh|en|ja|ko|auto language: null # zh|en|ja|ko|auto
preferred_image_backend: auto # auto|ask|<backend-id>
custom_styles: custom_styles:
- name: my-style - name: my-style
description: "Style description" description: "Style description"
@@ -49,6 +51,7 @@ custom_styles:
| `preferred_style.description` | string | "" | Custom notes/override | | `preferred_style.description` | string | "" | Custom notes/override |
| `preferred_layout` | string | null | Layout preference or null | | `preferred_layout` | string | null | Layout preference or null |
| `language` | string | null | Output language (null = auto-detect) | | `language` | string | null | Output language (null = auto-detect) |
| `preferred_image_backend` | string | `auto` | Image backend selection. `auto` = prefer runtime-native tool, fall back to the only installed backend, ask if multiple non-native are present. `ask` = always confirm on every run. `<backend-id>` (e.g., `codex-imagegen`, `baoyu-imagine`, `image_generate`) = pin this backend when available; fall back to `auto` when it isn't. Absent = `auto`. Resolution logic is documented in `SKILL.md`'s `## Image Generation Tools` section. |
| `custom_styles` | array | [] | User-defined styles | | `custom_styles` | array | [] | User-defined styles |
## Position Options ## Position Options
@@ -104,6 +107,8 @@ preferred_layout: dense
language: zh language: zh
preferred_image_backend: codex-imagegen
custom_styles: custom_styles:
- name: corporate - name: corporate
description: "Professional B2B style" description: "Professional B2B style"