1实现原理 · 为什么它能做到
实现方式是自建 provider 适配层:每个厂商一个模块,统一导出 generateImage(prompt, model, args),由主脚本按 provider 分派;请求体/尺寸/质量规则各自实现。
const imageData = await task.providerModule.generateImage(task.prompt, task.model, task.args);
provider 自动选择靠『哪些 key 存在』判定,codex-cli 被明确排除在自动选择之外。
const hasGoogle = !!(process.env.GOOGLE_API_KEY || process.env.GEMINI_API_KEY);
密钥与模型配置有明确优先级链:CLI > EXTEND.md > 环境变量 > <cwd>/.baoyu-skills/.env > ~/.baoyu-skills/.env,缺 key 时按 provider 报错并给获取地址。
Env file load order: CLI args > EXTEND.md > process.env > <cwd>/.baoyu-skills/.env > ~/.baoyu-skills/.env
批量并行是真的 worker 池 + provider 级闸门(并发上限与启动间隔),每张图最多重试 3 次。
const enoughCapacity = current.active < limit.concurrency;
批量任务由 JSON 文件驱动,另带一个组装器把 outline.md + prompts/ 目录拼成 batch.json,服务于文章配图流水线。
# Build a batch file from outline.md + prompts/ (e.g. baoyu-article-illustrator output)
codex-cli provider 不用 API key,而是 spawn 本地 codex CLI(订阅登录态)并跑同目录的 codex-imagegen 包装脚本;包装层会校验本轮是否真的调用过 image_gen。
const child = spawn(command, args, { stdio: ["ignore", "pipe", "pipe"] });
参考图身份保持不是玄学,SKILL.md 给出具体提示词纪律:短硬的身份保持句 + 明确允许改动的维度,避免把参考图换成一段泛化描述。
Do not redesign it or create a similar-looking new subject.
质量与尺寸有两套映射:预设 normal/2k(默认 2k)映射到各家参数;OpenAI 原生走 quality=medium/high 与 2048px 级合法尺寸,并约束 16 的倍数/最大边/长宽比。
width/height must be multiples of 16, max edge 3840px, ratio no wider than 3:1
2核心能力
3外部依赖
| 类型 | 依赖 |
|---|---|
| api | OpenAI Images API(gpt-image-2.5-flare 默认) |
| api | Azure OpenAI(deployment + api-version) |
| api | Google Gemini 图像生成(gemini-3-pro-image 默认) |
| api | OpenRouter(/chat/completions 流程) |
| api | 阿里云 DashScope(qwen-image-2.0-pro 默认) |
| api | Z.AI / 智谱(GLM-Image、cogview-4) |
| api | MiniMax image-01 |
| api | 火山引擎即梦(Jimeng,V4 签名,AccessKey/SecretKey) |
| api | 火山引擎 ARK / Seedream(豆包) |
| api | Replicate(nano-banana / seedream / wan 等家族) |
| api | Agnes |
| cli | codex CLI(本地订阅登录态;codex exec 通道) |
| cli | bun(运行 TS 脚本;缺 bun 时 npx -y bun) |
4风险提醒 风险提醒:红色 · 谨慎使用
- codex-cli 通道的安全降级与 prompt 注入面(判红主因) — `codex exec --sandbox danger-full-access` 关闭沙箱,且用户 prompt 被逐字拼进该 agent 的指令;若 prompt 来自不可信来源(网页、第三方 outline、他人提供的 prompts/ 目录),等同让无沙箱 agent 执行其内容。建议仅在 prompt 来源可控时使用该通道,或改走 API provider。
- 多密钥长期驻留在 dotenv 文件里 — 同时支持 <cwd>/.baoyu-skills/.env 与 ~/.baoyu-skills/.env,11 家厂商密钥可能长期落盘;任一被注入到 cwd 的项目目录读取,都会把该目录下真实密钥喂给脚本。
- 端点可被环境变量整体改写到自建网关 — <PROVIDER>_BASE_URL / OPENAI_BASE_URL / AZURE_OPENAI_BASE_URL 可由 env 或 EXTEND.md 指定,意味着密钥可能被送到非官方域名;使用前应确认这些变量未被他人预置。
- 成本与配额不可控地放大 — 批量默认 10 workers、每图最多 3 次重试,异常时可能对同一 prompt 反复计费;高分辨率/4K 与 12 家 provider 混用时成本差异很大,无内置预算上限。
5第二遍独立确认
- [ok] 12 家 provider 的端点与默认模型 — 逐个文件核对:openai.ts(api.openai.com/v1, gpt-image-2.5-flare)、azure.ts、google.ts(gemini-3-pro-image)、openrouter.ts、dashscope.ts(qwen-image-2.0-pro)、zai.ts、minimax.ts、jimeng.ts(jimeng_t2i_v40)、seedream.ts(doubao-seedream-5-0-260128)、replicate.ts(google/nano-banana-2)、agnes.ts(agnes-image-2.5-flash)、codex-cli.ts;与 SKILL.md 描述一致。
- [ok] 密钥读取清单 — SKILL.md 的 Environment Variables 表逐项在代码中命中对应 process.env 读取;另有 <PROVIDER>_BASE_URL 覆盖(jest 风格测试里也验证了 base URL 拼接)。
- [ok] codex-cli 存在 --sandbox danger-full-access(安全降级) — skills/baoyu-image-gen/scripts/codex-imagegen/spawn.ts 内 args 含 '"--sandbox"' 与 '"danger-full-access"';同目录 main.ts 注释与 assertSafePath 佐证该指令会被直接交给 codex。
- [ok] prompt 被逐字插入无沙箱 agent 指令 — codex-imagegen/main.ts 的 buildInstruction 返回模板内含 'PROMPT:' 后接 ${prompt},逐字使用;main.ts:104-109 注释说明只对 output/ref 路径做元字符校验,未覆盖 prompt 内容。
- [ok] codex-cli 不会被自动选中(红线触发条件) — SKILL.md Provider Selection 第 5 条与 main.ts 的 has* 判定均不含 codex-cli;需显式 --provider 或 EXTEND.md。
- [ok] 批量并行与重试参数 — main.ts 常量 MAX_ATTEMPTS=3、DEFAULT_MAX_WORKERS=10、provider 级 concurrency/startIntervalMs 表(codex-cli 为 concurrency=1/2000ms),与 SKILL.md 文案一致。
- [ok] 『Codex OAuth 不等于 API key』的说明与代码一致 — SKILL.md 明写不要把 Codex OAuth token 塞进 OPENAI_API_KEY;代码中 openai provider 只读 OPENAI_API_KEY,codex-cli 走独立 spawn 通道,未混用。
- [discrepancy] 红线判级与上游口头结论的关系 — 批4 口径曾一度把 image-gen 判为 orange(理由假设『无绕过/降级』)。本目录 evidence 与该假设不符:目录内确含 `--sandbox danger-full-access` 与 raw prompt 插值(上方两条 ok)。故按『证据优先』记 red,并在 reason 写明触发条件(仅 codex-cli 通道);默认 provider 路径仍为橙级行为。
6结论
4faafab87aede136…1567581c26