imgrelay 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,8 +3,8 @@
3
3
  在 Codex 中用自然语言调用第三方中转站生成图片,保存并展示原图。
4
4
  配置一次供应商、密钥和默认模型,即可在不同项目中复用。
5
5
 
6
- ImgRelay 由 CLI 和 Codex Skill 组成:CLI 负责配置、请求和文件保存,Skill 负责理解需求、
7
- 准备提示词和呈现结果。目前支持 OpenAI Images 兼容接口的文生图。
6
+ ImgRelay 提供负责配置和生图的 CLI,以及负责准备提示词、调用 CLI 和展示结果的 Codex Skill。
7
+ 支持 OpenAI Images 兼容接口的文生图。
8
8
 
9
9
  ## 快速上手
10
10
 
@@ -17,32 +17,27 @@ npm install -g imgrelay
17
17
  npx skills add bingwu-devkit/imgrelay --skill imgrelay
18
18
  ```
19
19
 
20
- 两者分开安装:npm 安装提供 `imgrelay` 命令,Skills CLI 安装 Skill。
21
20
  按 Skills CLI 的提示选择 Codex、安装范围和安装方式。
22
21
 
23
22
  ### 2. 配置中转站
24
23
 
25
- 在交互终端中运行,`relay` 是你为供应商取的名称:
24
+ 打开终端运行,`relay` 是你为供应商取的名称:
26
25
 
27
26
  ```bash
28
- imgrelay provider add relay
29
- imgrelay provider use relay
30
- imgrelay doctor --provider relay
27
+ imgrelay provider add relay --default
31
28
  ```
32
29
 
33
- 按提示输入 API 基础地址、API Key 并选择默认模型;地址通常形如
34
- `https://relay.example/v1`。密钥隐藏输入,模型列表不可用时可以手动填写模型 ID。
35
- 完成交互后统一保存配置,这个流程不会生成图片。
30
+ 按提示填写 API 基础地址、API Key 和默认模型。地址通常形如
31
+ `https://relay.example/v1`;密钥通过隐藏输入填写,模型列表不可用时可手动输入模型 ID。
36
32
 
37
- 使用 Cubence 时,可以用预设创建配置并设为默认:
33
+ 使用 Cubence 时,可通过预设填写地址和默认参数:
38
34
 
39
35
  ```bash
40
36
  imgrelay provider add cubence --preset cubence --default
41
37
  ```
42
38
 
43
- 配置保存在用户主目录的 `~/.imgrelay/`,跨项目复用。API Key 明文存储在 `config.json`,
44
- 请通过上述交互命令输入密钥,无需发给 Codex。`doctor` 检查配置和模型接口;
45
- 检查成功不代表所有生成参数都可用。
39
+ 配置保存在用户主目录的 `~/.imgrelay/`,跨项目复用。API Key 以明文保存在本机配置中,
40
+ 通过上述交互命令输入即可。
46
41
 
47
42
  ### 3. 在 Codex 中生成图片
48
43
 
@@ -56,48 +51,87 @@ $imgrelay 生成一张戴宇航员头盔的猫,用作博客封面,横版。
56
51
  用 imgrelay 生图,提示词请原样使用:一只橘猫趴在窗边,午后自然光。
57
52
  ```
58
53
 
59
- Skill 使用你指定的供应商、模型和参数,未指定时沿用本机默认配置。
60
- 对于简短需求,Codex 会围绕用途补足提示词;明确要求原样使用时保留原文。
61
- 生成后展示已保存的图片,并说明供应商、请求模型和保存位置。
54
+ 可在请求中指定供应商、模型、数量、尺寸或保存位置,其余设置沿用本机默认配置。
55
+ 对于简短需求,Codex 会围绕用途补足提示词;需要使用现成提示词时,说明“原样使用”即可。
62
56
 
63
- 默认输出在当前工作目录的 `output/imagegen/`,包含原图和生成记录。
64
- 也可以在请求中指定目录或文件名。
57
+ 生成后,Codex 会展示已保存的图片,并说明供应商、请求模型和保存位置。
58
+ 默认输出在当前项目的 `output/imagegen/`,包含原图和生成记录。
65
59
 
66
60
  ## 直接使用 CLI
67
61
 
68
- 不通过 Codex 也可以生成图片:
62
+ ### 从提示词文件生成
63
+
64
+ 新建 `prompt.txt`,写入想要生成的内容,例如:
65
+
66
+ ```text
67
+ 一只戴宇航员头盔的猫,蓝色背景。
68
+ 完整角色,横向构图,适合作为博客封面。
69
+ ```
70
+
71
+ 在文件所在目录运行:
72
+
73
+ ```bash
74
+ imgrelay generate --prompt-file ./prompt.txt
75
+ ```
76
+
77
+ ### 指定保存位置
78
+
79
+ ```bash
80
+ imgrelay generate --prompt-file ./prompt.txt --output-dir ./images --filename cat.png
81
+ ```
82
+
83
+ ### 选择供应商、模型或数量
84
+
85
+ ```bash
86
+ imgrelay generate --prompt-file ./prompt.txt --provider relay --model vendor-model --n 2
87
+ ```
88
+
89
+ `relay` 使用你已配置的供应商名称,`vendor-model` 替换为该供应商提供的模型 ID。
90
+ 本次指定的设置仅用于这次生成。尺寸、质量和格式等选项见 [CLI 参考](https://github.com/bingwu-devkit/imgrelay/blob/main/docs/cli-reference.md)。
91
+
92
+ ### 先预览配置(可选)
93
+
94
+ 想先查看本次使用的模型、参数和保存位置时,加上 `--dry-run`:
69
95
 
70
96
  ```bash
71
- imgrelay generate --prompt "一只戴宇航员头盔的猫"
72
- imgrelay generate --provider relay --prompt "极简风格的森林插画" --n 2 --json
73
- imgrelay generate --prompt "一只橘猫趴在窗边" --output-dir ./images --filename cat.png
97
+ imgrelay generate --prompt-file ./prompt.txt --dry-run --json
74
98
  ```
75
99
 
76
- 本次参数覆盖不会修改默认配置。CLI 原样发送 `--prompt`,不自动改写提示词。
77
- 尺寸、质量和格式是否可用取决于模型与供应商;完整选项见 `imgrelay generate --help`。
100
+ 这条命令只预览配置,不生成图片,也不消耗生图额度。
101
+
102
+ ## 管理配置
78
103
 
79
104
  | 常用命令 | 用途 |
80
105
  | ---------------------------------- | ------------------------------ |
81
106
  | `imgrelay provider list` | 查看供应商和默认项 |
82
- | `imgrelay provider show relay` | 查看供应商的脱敏配置 |
83
- | `imgrelay provider edit relay` | 修改配置或通过隐藏输入更新密钥 |
107
+ | `imgrelay provider show relay` | 查看供应商配置 |
108
+ | `imgrelay provider edit relay` | 修改地址、密钥、模型和默认参数 |
84
109
  | `imgrelay provider use relay` | 切换默认供应商 |
85
- | `imgrelay models --provider relay` | 查询模型列表,支持 `--refresh` |
86
- | `imgrelay doctor --provider relay` | 检查配置和模型接口,不生成图片 |
110
+ | `imgrelay models --provider relay` | 查询可用模型 |
111
+ | `imgrelay doctor --provider relay` | 检查配置和模型接口连接 |
112
+
113
+ 命令后加 `--help` 可查看完整选项。需要在脚本中读取结果时加 `--json`;
114
+ 添加供应商和更新密钥时,使用上表中的交互命令。
115
+
116
+ ## 常见问题
117
+
118
+ **图片保存在哪里?** 默认在运行命令的目录下的 `output/imagegen/`。
119
+ 用 `--output-dir` 指定其他目录,生成结果中也会显示保存路径。
120
+
121
+ **文件已经存在怎么办?** 更换 `--filename`,或在需要覆盖时加 `--overwrite`。
87
122
 
88
- 命令支持 `--help` 和 `--json`。JSON 模式关闭交互,标准输出只有一个最终 JSON,
89
- 进度输出到标准错误;新增供应商或更新密钥时使用不带 `--json` 的交互命令。
123
+ **找不到想用的模型怎么办?** 根据供应商提供的模型 ID,用 `--model` 指定;
124
+ 也可以运行 `provider edit` 修改默认模型。
90
125
 
91
- ## 使用须知
126
+ **生成等了很久怎么办?** 默认等待 10 分钟,可用 `--timeout` 调整等待秒数。
127
+ 超时或断网后,先到供应商后台确认请求状态,再决定是否重新生成。
92
128
 
93
- - 图片按原始字节保存,默认不覆盖已有文件;需要覆盖时显式使用 `--overwrite`。
94
- - 生成默认等待 600 秒。超时或断网后,上游可能仍在生成;工具不会自动重提、换模型或补单。
95
- - 部分图片失败时仍保留已保存的结果;非零退出码不一定意味着没有图片。
96
- - 模型列表不可用时仍可手动指定模型;图片编辑及非 OpenAI Images 协议目前不支持。
129
+ **只有部分图片成功怎么办?** 已保存的图片仍可使用,查看结果中的失败原因,
130
+ 再决定是否需要生成更多图片。
97
131
 
98
132
  ## 详细文档
99
133
 
100
- - [CLI 参考](https://github.com/bingwu-devkit/imgrelay/blob/main/docs/cli-reference.md):完整命令、兼容配置、存储方式、JSON 结果与退出码。
134
+ - [CLI 参考](https://github.com/bingwu-devkit/imgrelay/blob/main/docs/cli-reference.md):按场景使用命令、配置选项、脚本调用与问题处理。
101
135
  - [开发与发布](https://github.com/bingwu-devkit/imgrelay/blob/main/docs/development.md):源码运行、验证、打包和发布流程。
102
136
 
103
137
  ## 许可证
package/dist/index.mjs CHANGED
@@ -4,8 +4,8 @@ import { access, lstat, mkdir, open, readFile, rename, rmdir, unlink, writeFile
4
4
  import { basename, dirname, join, parse, resolve } from "node:path";
5
5
  import { fileTypeFromBuffer } from "file-type";
6
6
  import { imageSize } from "image-size";
7
- import { z } from "zod";
8
7
  import { setTimeout } from "node:timers/promises";
8
+ import { z } from "zod";
9
9
  import { homedir } from "node:os";
10
10
  import { Command, CommanderError } from "commander";
11
11
  import * as prompts from "@clack/prompts";
@@ -49,7 +49,7 @@ var Redactor = class {
49
49
  value(value) {
50
50
  if (typeof value === "string") return this.text(value);
51
51
  if (Array.isArray(value)) return value.map((item) => this.value(item));
52
- if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([key, item]) => [this.text(key), this.value(item)]));
52
+ if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([key, item]) => [this.text(key), key === "promptSha256" && typeof item === "string" && /^[a-f0-9]{64}$/.test(item) ? item : this.value(item)]));
53
53
  return value;
54
54
  }
55
55
  error(error) {
@@ -64,6 +64,110 @@ var Redactor = class {
64
64
  };
65
65
  }
66
66
  };
67
+ function isNotFound(error) {
68
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
69
+ }
70
+ async function assertRegular(path) {
71
+ const stat = await lstat(path);
72
+ if (!stat.isFile() || stat.isSymbolicLink()) throw new ImgRelayError("credential_error", "配置或凭据文件必须是普通文件,不能使用符号链接");
73
+ }
74
+ async function writeAtomic(path, value) {
75
+ const temporary = join(dirname(path), `.${randomUUID()}.tmp`);
76
+ const handle = await open(temporary, "wx");
77
+ try {
78
+ await handle.writeFile(`${JSON.stringify(value, null, 2)}\n`, "utf8");
79
+ await handle.sync();
80
+ await handle.close();
81
+ await rename(temporary, path);
82
+ } finally {
83
+ await handle.close().catch(() => {});
84
+ await unlink(temporary).catch(() => {});
85
+ }
86
+ }
87
+ async function readJson(path) {
88
+ await assertRegular(path);
89
+ return JSON.parse(await readFile(path, "utf8"));
90
+ }
91
+ const MAX_JSON_BYTES = 134217728;
92
+ const MAX_IMAGE_BYTES = 33554432;
93
+ async function readBounded(response, limit) {
94
+ if (Number(response.headers.get("content-length")) > limit) {
95
+ await response.body?.cancel();
96
+ throw new ImgRelayError("invalid_response", "上游响应超过大小限制", 3);
97
+ }
98
+ if (!response.body) return Buffer.alloc(0);
99
+ const reader = response.body.getReader();
100
+ const chunks = [];
101
+ let size = 0;
102
+ try {
103
+ for (;;) {
104
+ const { value, done } = await reader.read();
105
+ if (done) break;
106
+ size += value.byteLength;
107
+ if (size > limit) throw new ImgRelayError("invalid_response", "上游响应超过大小限制", 3);
108
+ chunks.push(value);
109
+ }
110
+ return Buffer.concat(chunks, size);
111
+ } finally {
112
+ await reader.cancel().catch(() => {});
113
+ reader.releaseLock();
114
+ }
115
+ }
116
+ function httpError(status, text, redactor) {
117
+ let detail = "";
118
+ try {
119
+ const parsed = JSON.parse(text);
120
+ if (parsed && typeof parsed === "object" && "error" in parsed) {
121
+ const error = parsed.error;
122
+ if (typeof error === "string") detail = error;
123
+ else if (error && typeof error === "object" && "message" in error && typeof error.message === "string") detail = error.message;
124
+ }
125
+ } catch {}
126
+ let category = "upstream_error";
127
+ if (status === 401 || status === 403) category = "auth_error";
128
+ else if (status === 429) category = "rate_limit";
129
+ else if (status === 402 || /insufficient.*(quota|balance)|余额不足/i.test(detail)) category = "quota_exceeded";
130
+ else if (/model.*(not found|not exist|unavailable|invalid)|模型.*(不存在|不可用)/i.test(detail)) category = "model_unavailable";
131
+ else if (/unsupported.*(param|size|quality|format)|unknown parameter|参数.*(不支持|无效)/i.test(detail)) category = "parameter_unsupported";
132
+ return new ImgRelayError(category, redactor.text(`上游返回 HTTP ${status}${detail ? `:${detail.slice(0, 1e3)}` : ",请检查接口、权限和请求参数"}`), 3, status);
133
+ }
134
+ async function requestJson(options) {
135
+ const method = options.method || "GET";
136
+ const attempts = method === "GET" && options.retry ? 2 : 1;
137
+ for (let attempt = 0; attempt < attempts; attempt++) {
138
+ const timeout = AbortSignal.timeout(Math.ceil((options.timeoutSeconds || 15) * 1e3));
139
+ const signal = options.signal ? AbortSignal.any([timeout, options.signal]) : timeout;
140
+ try {
141
+ const response = await fetch(options.url, {
142
+ method,
143
+ headers: {
144
+ Authorization: `Bearer ${options.key}`,
145
+ ...method === "POST" ? { "Content-Type": "application/json" } : {}
146
+ },
147
+ ...options.body === void 0 ? {} : { body: JSON.stringify(options.body) },
148
+ redirect: "manual",
149
+ signal
150
+ });
151
+ const text = (await readBounded(response, response.ok ? MAX_JSON_BYTES : 65536)).toString("utf8");
152
+ if (!response.ok) throw httpError(response.status, text, options.redactor);
153
+ try {
154
+ return JSON.parse(text);
155
+ } catch {
156
+ throw new ImgRelayError("invalid_response", "上游成功响应不是有效 JSON", 3);
157
+ }
158
+ } catch (error) {
159
+ if (options.signal?.aborted) throw new ImgRelayError("interrupted", method === "POST" ? "已停止本地等待,无法保证取消已提交的上游生成" : "用户中断请求", 130);
160
+ const retryable = !(error instanceof ImgRelayError) || error.httpStatus === 429 || error.httpStatus !== void 0 && error.httpStatus >= 500;
161
+ if (attempt + 1 < attempts && retryable) {
162
+ await setTimeout(150);
163
+ continue;
164
+ }
165
+ if (error instanceof ImgRelayError) throw error;
166
+ throw new ImgRelayError(method === "POST" ? "result_unknown" : "upstream_error", method === "POST" ? "生成请求超时或网络断开,结果未知;上游可能仍在生成,请勿直接重复提交" : "模型查询超时或网络失败,请检查地址和网络", 3);
167
+ }
168
+ }
169
+ throw new ImgRelayError("internal_error", "请求执行状态无效", 1);
170
+ }
67
171
  function parseApiUrl(value) {
68
172
  let url;
69
173
  try {
@@ -246,109 +350,86 @@ function resolveParameters(provider, model, supplied) {
246
350
  }
247
351
  return result;
248
352
  }
249
- function isNotFound(error) {
250
- return error instanceof Error && "code" in error && error.code === "ENOENT";
251
- }
252
- async function assertRegular(path) {
253
- const stat = await lstat(path);
254
- if (!stat.isFile() || stat.isSymbolicLink()) throw new ImgRelayError("credential_error", "配置或凭据文件必须是普通文件,不能使用符号链接");
255
- }
256
- async function writeAtomic(path, value) {
257
- const temporary = join(dirname(path), `.${randomUUID()}.tmp`);
258
- const handle = await open(temporary, "wx");
259
- try {
260
- await handle.writeFile(`${JSON.stringify(value, null, 2)}\n`, "utf8");
261
- await handle.sync();
262
- await handle.close();
263
- await rename(temporary, path);
264
- } finally {
265
- await handle.close().catch(() => {});
266
- await unlink(temporary).catch(() => {});
267
- }
268
- }
269
- async function readJson(path) {
270
- await assertRegular(path);
271
- return JSON.parse(await readFile(path, "utf8"));
272
- }
273
- const MAX_JSON_BYTES = 134217728;
274
- const MAX_IMAGE_BYTES = 33554432;
275
- async function readBounded(response, limit) {
276
- if (Number(response.headers.get("content-length")) > limit) {
277
- await response.body?.cancel();
278
- throw new ImgRelayError("invalid_response", "上游响应超过大小限制", 3);
279
- }
280
- if (!response.body) return Buffer.alloc(0);
281
- const reader = response.body.getReader();
282
- const chunks = [];
283
- let size = 0;
284
- try {
285
- for (;;) {
286
- const { value, done } = await reader.read();
287
- if (done) break;
288
- size += value.byteLength;
289
- if (size > limit) throw new ImgRelayError("invalid_response", "上游响应超过大小限制", 3);
290
- chunks.push(value);
291
- }
292
- return Buffer.concat(chunks, size);
293
- } finally {
294
- await reader.cancel().catch(() => {});
295
- reader.releaseLock();
353
+ const parameterNames = [
354
+ "size",
355
+ "n",
356
+ "quality",
357
+ "outputFormat",
358
+ "responseFormat"
359
+ ];
360
+ /** Resolve local configuration without requiring credentials, network or filesystem writes. */
361
+ async function prepareRequest(store, options) {
362
+ if (!options.prompt.trim()) throw new ImgRelayError("input_error", "提示词不能为空");
363
+ for (const name of [
364
+ "provider",
365
+ "model",
366
+ "outputDir"
367
+ ]) if (options[name] !== void 0 && !options[name].trim()) throw new ImgRelayError("input_error", `${name} 不能为空`);
368
+ if (options.timeoutSeconds !== void 0 && (!Number.isFinite(options.timeoutSeconds) || options.timeoutSeconds <= 0 || options.timeoutSeconds > 2147483)) throw new ImgRelayError("input_error", "超时必须是有效的正数秒数");
369
+ if (options.filename !== void 0 && (!options.filename || basename(options.filename) !== options.filename || /[<>:"/\\|?*]/.test(options.filename) || options.filename.split("").some((character) => character.charCodeAt(0) < 32) || !parse(options.filename).name || [".", ".."].includes(options.filename))) throw new ImgRelayError("input_error", "--filename 必须是普通文件名,保存目录使用 --output-dir");
370
+ const selected = await store.selected(options.provider);
371
+ const model = (options.model ?? selected.provider.defaultModel ?? "").trim();
372
+ if (!model) throw new ImgRelayError("config_error", "未配置默认模型,请通过 --model 指定或运行 provider edit");
373
+ const supplied = {};
374
+ const parameterSources = {};
375
+ for (const name of parameterNames) {
376
+ const value = options[name];
377
+ if (value !== void 0) Object.assign(supplied, { [name]: value });
378
+ if (value !== void 0) parameterSources[name] = "explicit";
379
+ else if (selected.provider.defaults[name] !== void 0) parameterSources[name] = "provider_default";
380
+ else if (name === "n") parameterSources.n = "tool_default";
296
381
  }
382
+ return {
383
+ details: {
384
+ promptSource: options.promptSource ?? { type: "api" },
385
+ promptSha256: createHash("sha256").update(options.prompt, "utf8").digest("hex"),
386
+ promptCharacters: options.prompt.length,
387
+ promptUtf8Bytes: Buffer.byteLength(options.prompt, "utf8"),
388
+ provider: selected.name,
389
+ requestedModel: model,
390
+ parameters: {
391
+ n: 1,
392
+ ...selected.provider.defaults,
393
+ ...supplied
394
+ },
395
+ endpoint: resolveEndpoint(selected.provider.baseUrl, selected.provider.endpoints.generate || "/v1/images/generations"),
396
+ capabilityEvidence: {
397
+ known: Object.hasOwn(KNOWN_MODEL_CAPABILITIES, model) ? KNOWN_MODEL_CAPABILITIES[model] || null : null,
398
+ provider: Object.hasOwn(selected.provider.modelOverrides, model) ? selected.provider.modelOverrides[model] || null : null
399
+ },
400
+ outputDir: resolve(options.outputDir ?? "output/imagegen"),
401
+ filename: options.filename ?? null,
402
+ overwrite: Boolean(options.overwrite),
403
+ timeoutSeconds: options.timeoutSeconds ?? selected.provider.timeoutSeconds,
404
+ sources: {
405
+ provider: options.provider !== void 0 ? "explicit" : "default",
406
+ model: options.model !== void 0 ? "explicit" : "provider_default",
407
+ parameters: parameterSources,
408
+ outputDir: options.outputDir !== void 0 ? "explicit" : "tool_default",
409
+ filename: options.filename !== void 0 ? "explicit" : "tool_default",
410
+ overwrite: options.overwrite ? "explicit" : "tool_default",
411
+ timeoutSeconds: options.timeoutSeconds !== void 0 ? "explicit" : "provider_default"
412
+ }
413
+ },
414
+ provider: selected.provider,
415
+ supplied
416
+ };
297
417
  }
298
- function httpError(status, text, redactor) {
299
- let detail = "";
300
- try {
301
- const parsed = JSON.parse(text);
302
- if (parsed && typeof parsed === "object" && "error" in parsed) {
303
- const error = parsed.error;
304
- if (typeof error === "string") detail = error;
305
- else if (error && typeof error === "object" && "message" in error && typeof error.message === "string") detail = error.message;
306
- }
307
- } catch {}
308
- let category = "upstream_error";
309
- if (status === 401 || status === 403) category = "auth_error";
310
- else if (status === 429) category = "rate_limit";
311
- else if (status === 402 || /insufficient.*(quota|balance)|余额不足/i.test(detail)) category = "quota_exceeded";
312
- else if (/model.*(not found|not exist|unavailable|invalid)|模型.*(不存在|不可用)/i.test(detail)) category = "model_unavailable";
313
- else if (/unsupported.*(param|size|quality|format)|unknown parameter|参数.*(不支持|无效)/i.test(detail)) category = "parameter_unsupported";
314
- return new ImgRelayError(category, redactor.text(`上游返回 HTTP ${status}${detail ? `:${detail.slice(0, 1e3)}` : ",请检查接口、权限和请求参数"}`), 3, status);
418
+ function validateRequest(prepared) {
419
+ prepared.details.parameters = resolveParameters(prepared.provider, prepared.details.requestedModel, prepared.supplied);
420
+ for (const name of parameterNames) if (prepared.details.parameters[name] === void 0) delete prepared.details.sources.parameters[name];
315
421
  }
316
- async function requestJson(options) {
317
- const method = options.method || "GET";
318
- const attempts = method === "GET" && options.retry ? 2 : 1;
319
- for (let attempt = 0; attempt < attempts; attempt++) {
320
- const timeout = AbortSignal.timeout(Math.ceil((options.timeoutSeconds || 15) * 1e3));
321
- const signal = options.signal ? AbortSignal.any([timeout, options.signal]) : timeout;
322
- try {
323
- const response = await fetch(options.url, {
324
- method,
325
- headers: {
326
- Authorization: `Bearer ${options.key}`,
327
- ...method === "POST" ? { "Content-Type": "application/json" } : {}
328
- },
329
- ...options.body === void 0 ? {} : { body: JSON.stringify(options.body) },
330
- redirect: "manual",
331
- signal
332
- });
333
- const text = (await readBounded(response, response.ok ? MAX_JSON_BYTES : 65536)).toString("utf8");
334
- if (!response.ok) throw httpError(response.status, text, options.redactor);
335
- try {
336
- return JSON.parse(text);
337
- } catch {
338
- throw new ImgRelayError("invalid_response", "上游成功响应不是有效 JSON", 3);
339
- }
340
- } catch (error) {
341
- if (options.signal?.aborted) throw new ImgRelayError("interrupted", method === "POST" ? "已停止本地等待,无法保证取消已提交的上游生成" : "用户中断请求", 130);
342
- const retryable = !(error instanceof ImgRelayError) || error.httpStatus === 429 || error.httpStatus !== void 0 && error.httpStatus >= 500;
343
- if (attempt + 1 < attempts && retryable) {
344
- await setTimeout(150);
345
- continue;
346
- }
347
- if (error instanceof ImgRelayError) throw error;
348
- throw new ImgRelayError(method === "POST" ? "result_unknown" : "upstream_error", method === "POST" ? "生成请求超时或网络断开,结果未知;上游可能仍在生成,请勿直接重复提交" : "模型查询超时或网络失败,请检查地址和网络", 3);
349
- }
350
- }
351
- throw new ImgRelayError("internal_error", "请求执行状态无效", 1);
422
+ async function previewGenerate(store, options) {
423
+ const prepared = await prepareRequest(store, options);
424
+ validateRequest(prepared);
425
+ if (options.signal?.aborted) throw new ImgRelayError("interrupted", "用户中断,未提交生成请求", 130);
426
+ return {
427
+ ...prepared.details,
428
+ dryRun: true,
429
+ credentialConfigured: Boolean(prepared.provider.apiKey),
430
+ submissionStatus: "not_submitted",
431
+ willSubmitNetworkRequest: false
432
+ };
352
433
  }
353
434
  function base64Bytes(value) {
354
435
  const encoded = value.replace(/^data:image\/[^;,]+;base64,/, "").replace(/\s/g, "");
@@ -400,42 +481,16 @@ function usageNumbers(value, depth = 0) {
400
481
  return entries.length ? Object.fromEntries(entries) : void 0;
401
482
  }
402
483
  async function generate(store, options) {
403
- if (!options.prompt.trim()) throw new ImgRelayError("input_error", "提示词不能为空");
404
- if (options.timeoutSeconds !== void 0 && (!Number.isFinite(options.timeoutSeconds) || options.timeoutSeconds <= 0 || options.timeoutSeconds > 2147483)) throw new ImgRelayError("input_error", "超时必须是有效的正数秒数");
405
- if (options.filename && (basename(options.filename) !== options.filename || /[<>:"/\\|?*]/.test(options.filename) || options.filename.split("").some((character) => character.charCodeAt(0) < 32) || !parse(options.filename).name || [".", ".."].includes(options.filename))) throw new ImgRelayError("input_error", "--filename 必须是普通文件名,保存目录使用 --output-dir");
406
- const selected = await store.selected(options.provider);
407
- const model = (options.model || selected.provider.defaultModel || "").trim();
408
- if (!model) throw new ImgRelayError("config_error", "未配置默认模型,请通过 --model 指定或运行 provider edit");
409
- const key = await store.key(selected.provider);
410
- const outputDir = resolve(options.outputDir || "output/imagegen");
484
+ const prepared = await prepareRequest(store, options);
485
+ const { outputDir, requestedModel: model } = prepared.details;
486
+ const key = await store.key(prepared.provider);
411
487
  const requestId = randomUUID();
412
488
  const recordPath = join(outputDir, `${requestId}-report.json`);
413
- const supplied = {};
414
- for (const name of [
415
- "size",
416
- "n",
417
- "quality",
418
- "outputFormat",
419
- "responseFormat"
420
- ]) {
421
- const value = options[name];
422
- if (value !== void 0) Object.assign(supplied, { [name]: value });
423
- }
424
489
  const data = {
490
+ ...prepared.details,
425
491
  requestId,
426
- provider: selected.name,
427
- requestedModel: model,
428
- requestedCount: supplied.n || selected.provider.defaults.n || 1,
492
+ requestedCount: prepared.details.parameters.n || 1,
429
493
  returnedCount: 0,
430
- parameters: {
431
- ...selected.provider.defaults,
432
- ...supplied
433
- },
434
- endpoint: resolveEndpoint(selected.provider.baseUrl, selected.provider.endpoints.generate || "/v1/images/generations"),
435
- capabilityEvidence: {
436
- known: Object.hasOwn(KNOWN_MODEL_CAPABILITIES, model) ? KNOWN_MODEL_CAPABILITIES[model] || null : null,
437
- provider: Object.hasOwn(selected.provider.modelOverrides, model) ? selected.provider.modelOverrides[model] || null : null
438
- },
439
494
  images: [],
440
495
  failures: [],
441
496
  recordPath,
@@ -468,7 +523,8 @@ async function generate(store, options) {
468
523
  }
469
524
  let outcome;
470
525
  try {
471
- data.parameters = resolveParameters(selected.provider, model, supplied);
526
+ validateRequest(prepared);
527
+ data.parameters = prepared.details.parameters;
472
528
  const body = {
473
529
  model,
474
530
  prompt: options.prompt
@@ -489,7 +545,7 @@ async function generate(store, options) {
489
545
  redactor: store.redactor,
490
546
  method: "POST",
491
547
  body,
492
- timeoutSeconds: options.timeoutSeconds || selected.provider.timeoutSeconds,
548
+ timeoutSeconds: data.timeoutSeconds,
493
549
  ...options.signal ? { signal: options.signal } : {}
494
550
  });
495
551
  data.submissionStatus = "result_received";
@@ -862,7 +918,63 @@ var Store = class {
862
918
  };
863
919
  //#endregion
864
920
  //#region package.json
865
- var version = "0.2.1";
921
+ var version = "0.3.0";
922
+ //#endregion
923
+ //#region src/prompt.ts
924
+ function interrupted() {
925
+ return new ImgRelayError("interrupted", "用户中断读取提示词,未提交生成请求", 130);
926
+ }
927
+ async function readPrompt(flags, signal, stdin = process.stdin) {
928
+ if (Number(flags.promptFile !== void 0) + Number(Boolean(flags.promptStdin)) !== 1) throw new ImgRelayError("input_error", "必须且只能指定 --prompt-file 或 --prompt-stdin");
929
+ if (signal?.aborted) throw interrupted();
930
+ let bytes;
931
+ let promptSource;
932
+ if (flags.promptFile !== void 0) {
933
+ if (!flags.promptFile.trim()) throw new ImgRelayError("input_error", "--prompt-file 路径不能为空");
934
+ const path = resolve(flags.promptFile);
935
+ try {
936
+ bytes = await readFile(path, signal ? { signal } : {});
937
+ } catch {
938
+ if (signal?.aborted) throw interrupted();
939
+ throw new ImgRelayError("input_error", "无法读取 --prompt-file;请检查文件路径及访问权限");
940
+ }
941
+ promptSource = {
942
+ type: "file",
943
+ path
944
+ };
945
+ } else {
946
+ if (stdin.isTTY) throw new ImgRelayError("input_error", "--prompt-stdin 需要管道或重定向输入;也可使用 --prompt-file");
947
+ const abort = () => stdin.destroy(interrupted());
948
+ signal?.addEventListener("abort", abort, { once: true });
949
+ const chunks = [];
950
+ try {
951
+ for await (const chunk of stdin) chunks.push(Buffer.from(chunk));
952
+ bytes = Buffer.concat(chunks);
953
+ } catch {
954
+ if (signal?.aborted) throw interrupted();
955
+ throw new ImgRelayError("input_error", "无法读取 stdin 提示词");
956
+ } finally {
957
+ signal?.removeEventListener("abort", abort);
958
+ }
959
+ promptSource = { type: "stdin" };
960
+ }
961
+ if (signal?.aborted) throw interrupted();
962
+ let prompt;
963
+ try {
964
+ prompt = new TextDecoder("utf-8", {
965
+ fatal: true,
966
+ ignoreBOM: true
967
+ }).decode(bytes);
968
+ } catch {
969
+ throw new ImgRelayError("input_error", "提示词必须是有效 UTF-8 文本");
970
+ }
971
+ if (prompt.startsWith("")) prompt = prompt.slice(1);
972
+ if (!prompt.trim()) throw new ImgRelayError("input_error", "提示词不能为空或全空白");
973
+ return {
974
+ prompt,
975
+ promptSource
976
+ };
977
+ }
866
978
  //#endregion
867
979
  //#region src/provider.ts
868
980
  function answer(value) {
@@ -1085,13 +1197,12 @@ program.command("doctor").description("检查配置与模型接口,不生成
1085
1197
  ...result.error ? { error: result.error } : {}
1086
1198
  });
1087
1199
  });
1088
- program.command("generate").description("生成图片并保存原图和记录").option("--prompt <文本>", "直接提供非空提示词(必填)").option("--provider <名称>", "本次使用的供应商").option("--model <ID>", "本次使用的模型").option("--size <尺寸>", "图片尺寸,如 auto 或 1024x1024").option("--n <数量>", "请求图片数量,不自动拆单").option("--quality <质量>", "请求质量").option("--output-format <格式>", "请求图片格式").option("--output-dir <目录>", "保存目录,默认 output/imagegen").option("--filename <名称>", "文件名;多图追加序号,扩展名按实际格式").option("--overwrite", "允许覆盖图片文件").option("--timeout <秒数>", "生成等待超时,默认 600 秒").action(async (flags) => {
1200
+ program.command("generate").description("生成图片并保存原图和记录").allowExcessArguments(false).option("--prompt-file <路径>", "读取 UTF-8 提示词文件,与 --prompt-stdin 互斥").option("--prompt-stdin", "从管道或重定向读取 UTF-8 提示词,与 --prompt-file 互斥").option("--dry-run", "离线预览有效请求,不联网、不写文件,无需密钥").option("--provider <名称>", "本次使用的供应商").option("--model <ID>", "本次使用的模型").option("--size <尺寸>", "图片尺寸,如 auto 或 1024x1024").option("--n <数量>", "请求图片数量,不自动拆单").option("--quality <质量>", "请求质量").option("--output-format <格式>", "请求图片格式").option("--output-dir <目录>", "保存目录,默认 output/imagegen").option("--filename <名称>", "文件名;多图追加序号,扩展名按实际格式").option("--overwrite", "允许覆盖图片文件").option("--timeout <秒数>", "生成等待超时,默认 600 秒").action(async (flags) => {
1089
1201
  const current = active("generate");
1090
- if (flags.prompt === void 0) throw new ImgRelayError("input_error", "请通过 --prompt 提供非空提示词");
1091
- const result = await generate(current, {
1092
- prompt: flags.prompt,
1093
- ...flags.provider ? { provider: flags.provider } : {},
1094
- ...flags.model ? { model: flags.model } : {},
1202
+ const options = {
1203
+ ...await readPrompt(flags, controller.signal),
1204
+ ...flags.provider !== void 0 ? { provider: flags.provider } : {},
1205
+ ...flags.model !== void 0 ? { model: flags.model } : {},
1095
1206
  ...flags.size !== void 0 ? { size: flags.size } : {},
1096
1207
  ...flags.n !== void 0 ? { n: Number(flags.n) } : {},
1097
1208
  ...flags.quality !== void 0 ? { quality: flags.quality } : {},
@@ -1102,7 +1213,12 @@ program.command("generate").description("生成图片并保存原图和记录").
1102
1213
  overwrite: Boolean(flags.overwrite),
1103
1214
  signal: controller.signal,
1104
1215
  progress: (message) => process.stderr.write(`${message}\n`)
1105
- });
1216
+ };
1217
+ if (flags.dryRun) {
1218
+ output(await previewGenerate(current, options));
1219
+ return;
1220
+ }
1221
+ const result = await generate(current, options);
1106
1222
  output(result.data, {
1107
1223
  status: result.status,
1108
1224
  exitCode: result.exitCode,
@@ -1120,7 +1236,9 @@ try {
1120
1236
  if (json) output({ help: helpOutput.trim() });
1121
1237
  process.exitCode = 0;
1122
1238
  } else {
1123
- const failure = error instanceof CommanderError ? new ImgRelayError("input_error", error.message) : error;
1239
+ const removedPrompt = error instanceof CommanderError && error.code === "commander.unknownOption" && (error.message.includes("'--prompt'") || error.message.includes("'--prompt="));
1240
+ if (removedPrompt) commandName = "generate";
1241
+ const failure = error instanceof CommanderError ? new ImgRelayError("input_error", removedPrompt ? "--prompt 已移除,请改用 --prompt-file <路径> 或 --prompt-stdin" : error.message) : error;
1124
1242
  const info = store ? store.redactor.error(failure) : {
1125
1243
  category: failure instanceof ImgRelayError ? failure.category : "internal_error",
1126
1244
  message: failure instanceof Error ? failure.message : "发生未知错误"
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["packageJson.version"],"sources":["../../core/dist/index.mjs","../package.json","../src/provider.ts","../src/index.ts"],"sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport { access, lstat, mkdir, open, readFile, rename, rmdir, unlink, writeFile } from \"node:fs/promises\";\nimport { basename, dirname, join, parse, resolve } from \"node:path\";\nimport { fileTypeFromBuffer } from \"file-type\";\nimport { imageSize } from \"image-size\";\nimport { z } from \"zod\";\nimport { setTimeout } from \"node:timers/promises\";\nimport { homedir } from \"node:os\";\n\n//#region src/errors.ts\nvar ImgRelayError = class extends Error {\n\tcategory;\n\texitCode;\n\thttpStatus;\n\tconstructor(category, message, exitCode = 2, httpStatus) {\n\t\tsuper(message);\n\t\tthis.name = \"ImgRelayError\";\n\t\tthis.category = category;\n\t\tthis.exitCode = exitCode;\n\t\tthis.httpStatus = httpStatus;\n\t}\n};\n/** Redact before serialization; never retain an upstream response as a diagnostic. */\nvar Redactor = class {\n\tsecrets = /* @__PURE__ */ new Set();\n\tadd(secret) {\n\t\tif (secret) this.secrets.add(secret);\n\t}\n\ttext(value) {\n\t\tlet text = value;\n\t\tfor (const secret of [...this.secrets].toSorted((a, b) => b.length - a.length)) text = text.replaceAll(secret, \"[REDACTED]\");\n\t\treturn text.replace(/https?:\\/\\/[^\\s<>\"']+/gi, (raw) => {\n\t\t\ttry {\n\t\t\t\tconst url = new URL(raw);\n\t\t\t\tif (url.username || url.password) {\n\t\t\t\t\turl.username = \"REDACTED\";\n\t\t\t\t\turl.password = \"\";\n\t\t\t\t}\n\t\t\t\tif (url.search) url.search = \"?REDACTED\";\n\t\t\t\tif (url.hash) url.hash = \"#REDACTED\";\n\t\t\t\treturn url.toString();\n\t\t\t} catch {\n\t\t\t\treturn \"[REDACTED_URL]\";\n\t\t\t}\n\t\t});\n\t}\n\tvalue(value) {\n\t\tif (typeof value === \"string\") return this.text(value);\n\t\tif (Array.isArray(value)) return value.map((item) => this.value(item));\n\t\tif (value && typeof value === \"object\") return Object.fromEntries(Object.entries(value).map(([key, item]) => [this.text(key), this.value(item)]));\n\t\treturn value;\n\t}\n\terror(error) {\n\t\tif (error instanceof ImgRelayError) return {\n\t\t\tcategory: error.category,\n\t\t\tmessage: this.text(error.message),\n\t\t\t...error.httpStatus === void 0 ? {} : { httpStatus: error.httpStatus }\n\t\t};\n\t\treturn {\n\t\t\tcategory: \"internal_error\",\n\t\t\tmessage: this.text(error instanceof Error ? error.message : \"发生未知错误\")\n\t\t};\n\t}\n};\n\n//#endregion\n//#region src/urls.ts\nfunction parseApiUrl(value) {\n\tlet url;\n\ttry {\n\t\turl = new URL(value);\n\t} catch {\n\t\tthrow new ImgRelayError(\"config_error\", \"API 地址必须是完整的 HTTP 或 HTTPS URL\");\n\t}\n\tif (![\"http:\", \"https:\"].includes(url.protocol) || url.username || url.password || url.search || url.hash) throw new ImgRelayError(\"config_error\", \"API 地址只能使用 HTTP(S),不能包含凭据、查询参数或片段\");\n\treturn url;\n}\nfunction normalizeBaseUrl(value) {\n\treturn normalizeAddress(value).baseUrl;\n}\nfunction normalizeAddress(value) {\n\tconst url = parseApiUrl(value);\n\tconst path = url.pathname.replace(/\\/+$/, \"\");\n\tconst isGeneration = path.endsWith(\"/images/generations\");\n\turl.pathname = isGeneration ? path.slice(0, -19) : path;\n\treturn {\n\t\tbaseUrl: url.toString().replace(/\\/+$/, \"\"),\n\t\t...isGeneration ? { generationPath: \"/images/generations\" } : {}\n\t};\n}\nfunction validateEndpoint(path) {\n\ttry {\n\t\treturn path.startsWith(\"/\") && !/[?#\\\\]/.test(path) && !path.includes(\"//\") && !path.split(\"/\").some((part) => [\"..\", \".\"].includes(decodeURIComponent(part)));\n\t} catch {\n\t\treturn false;\n\t}\n}\nfunction resolveEndpoint(baseUrl, endpoint) {\n\tif (!validateEndpoint(endpoint)) throw new ImgRelayError(\"config_error\", \"端点必须是路径,不能包含主机、查询参数或上级目录\");\n\tconst url = parseApiUrl(baseUrl);\n\tconst basePath = url.pathname.replace(/\\/+$/, \"\");\n\turl.pathname = `${basePath}${basePath.endsWith(\"/v1\") && endpoint.startsWith(\"/v1/\") ? endpoint.slice(3) : endpoint}`;\n\treturn url.toString();\n}\n\n//#endregion\n//#region src/schema.ts\nconst shortText = z.string().trim().min(1).max(256);\nconst providerNameSchema = z.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/);\nconst parameterSchema = z.strictObject({\n\tsize: shortText.optional(),\n\tn: z.number().int().positive().optional(),\n\tquality: shortText.optional(),\n\toutputFormat: shortText.optional(),\n\tresponseFormat: z.enum([\"url\", \"b64_json\"]).optional()\n});\nconst parameterCapabilitySchema = z.strictObject({\n\tsupported: z.boolean().optional(),\n\tvalues: z.array(shortText).min(1).optional(),\n\tmin: z.number().optional(),\n\tmax: z.number().optional()\n});\nconst modelCapabilitySchema = z.strictObject({\n\tsource: z.enum([\n\t\t\"official_documentation\",\n\t\t\"provider_override\",\n\t\t\"call_verification\"\n\t]).default(\"provider_override\"),\n\tsourceUrl: z.url().optional(),\n\tverifiedAt: z.iso.datetime().optional(),\n\tparameters: z.strictObject({\n\t\tsize: parameterCapabilitySchema.optional(),\n\t\tn: parameterCapabilitySchema.optional(),\n\t\tquality: parameterCapabilitySchema.optional(),\n\t\toutputFormat: parameterCapabilitySchema.optional(),\n\t\tresponseFormat: parameterCapabilitySchema.optional()\n\t})\n});\nconst endpointSchema = z.string().max(1024).refine((value) => {\n\ttry {\n\t\treturn validateEndpoint(value);\n\t} catch {\n\t\treturn false;\n\t}\n}, \"端点必须是有效路径\");\nconst providerSchema = z.strictObject({\n\tprotocol: z.literal(\"openai-images\"),\n\tbaseUrl: z.string(),\n\tapiKey: z.string().trim().min(1).refine((key) => !/[\\r\\n\\0]/.test(key), \"密钥不能包含换行或空字符\").optional(),\n\tdefaultModel: shortText.optional(),\n\tdefaults: parameterSchema.default({}),\n\tendpoints: z.strictObject({\n\t\tgenerate: endpointSchema.optional(),\n\t\tmodels: endpointSchema.optional()\n\t}).default({}),\n\tmodelOverrides: z.record(shortText, modelCapabilitySchema).default({}),\n\ttimeoutSeconds: z.number().positive().max(2147483).finite().default(600),\n\trevision: z.number().int().positive().default(1)\n}).transform((provider) => {\n\tconst address = normalizeAddress(provider.baseUrl);\n\treturn {\n\t\t...provider,\n\t\tbaseUrl: address.baseUrl,\n\t\tendpoints: address.generationPath && !provider.endpoints.generate ? {\n\t\t\t...provider.endpoints,\n\t\t\tgenerate: address.generationPath\n\t\t} : provider.endpoints\n\t};\n});\nconst configSchema = z.strictObject({\n\tschemaVersion: z.literal(1),\n\tdefaultProvider: providerNameSchema.optional(),\n\tproviders: z.record(providerNameSchema, providerSchema)\n});\nfunction parseProvider(input) {\n\tconst result = providerSchema.safeParse(input);\n\tif (!result.success) throw new ImgRelayError(\"config_error\", `供应商配置无效:${result.error.issues.map((issue) => `${issue.path.join(\".\")} ${issue.message}`).join(\";\")}`);\n\treturn result.data;\n}\nconst CUBENCE_PRESET = {\n\tprotocol: \"openai-images\",\n\tbaseUrl: \"https://api-lb.cubence.ai/v1\",\n\tdefaultModel: \"gpt-image-2.5-flare\",\n\tdefaults: {\n\t\tsize: \"auto\",\n\t\tn: 1,\n\t\tquality: \"high\",\n\t\toutputFormat: \"png\"\n\t}\n};\n\n//#endregion\n//#region src/capabilities.ts\nconst GPT_IMAGE_CAPABILITY = {\n\tsource: \"official_documentation\",\n\tsourceUrl: \"https://developers.openai.com/api/reference/python/resources/images/methods/generate\",\n\tverifiedAt: \"2026-10-10T10:03:00.000Z\",\n\tparameters: {\n\t\tn: {\n\t\t\tmin: 1,\n\t\t\tmax: 10\n\t\t},\n\t\tsize: { values: [\n\t\t\t\"auto\",\n\t\t\t\"1024x1024\",\n\t\t\t\"1536x1024\",\n\t\t\t\"1024x1536\"\n\t\t] },\n\t\tquality: { values: [\n\t\t\t\"auto\",\n\t\t\t\"low\",\n\t\t\t\"medium\",\n\t\t\t\"high\"\n\t\t] },\n\t\toutputFormat: { values: [\n\t\t\t\"png\",\n\t\t\t\"jpeg\",\n\t\t\t\"webp\"\n\t\t] },\n\t\tresponseFormat: { supported: false }\n\t}\n};\nconst KNOWN_MODEL_CAPABILITIES = {\n\t\"gpt-image-1\": GPT_IMAGE_CAPABILITY,\n\t\"gpt-image-1-mini\": GPT_IMAGE_CAPABILITY\n};\nfunction resolveParameters(provider, model, supplied) {\n\tconst parsed = parameterSchema.safeParse({\n\t\tn: 1,\n\t\t...provider.defaults,\n\t\t...supplied\n\t});\n\tif (!parsed.success) throw new ImgRelayError(\"input_error\", \"生成参数无效:数量必须是正整数,各参数必须是非空字符串\");\n\tconst result = parsed.data;\n\tconst known = Object.hasOwn(KNOWN_MODEL_CAPABILITIES, model) ? KNOWN_MODEL_CAPABILITIES[model] : void 0;\n\tconst override = Object.hasOwn(provider.modelOverrides, model) ? provider.modelOverrides[model] : void 0;\n\tconst limits = {\n\t\t...known?.parameters,\n\t\t...override?.parameters\n\t};\n\tfor (const name of [\n\t\t\"size\",\n\t\t\"n\",\n\t\t\"quality\",\n\t\t\"outputFormat\",\n\t\t\"responseFormat\"\n\t]) {\n\t\tconst value = result[name];\n\t\tconst limit = limits[name];\n\t\tif (value === void 0 || !limit) continue;\n\t\tif (limit.supported === false && name === \"n\" && supplied.n === void 0 && provider.defaults.n === void 0) {\n\t\t\tdelete result.n;\n\t\t\tcontinue;\n\t\t}\n\t\tif (limit.supported === false || limit.values && !limit.values.includes(String(value)) || typeof value === \"number\" && (limit.min !== void 0 && value < limit.min || limit.max !== void 0 && value > limit.max)) throw new ImgRelayError(\"parameter_unsupported\", `模型 ${model} 不支持参数 ${name}=${value};请检查模型能力或供应商覆盖`, 2);\n\t}\n\treturn result;\n}\n\n//#endregion\n//#region src/files.ts\nfunction isNotFound(error) {\n\treturn error instanceof Error && \"code\" in error && error.code === \"ENOENT\";\n}\nasync function assertRegular(path) {\n\tconst stat = await lstat(path);\n\tif (!stat.isFile() || stat.isSymbolicLink()) throw new ImgRelayError(\"credential_error\", \"配置或凭据文件必须是普通文件,不能使用符号链接\");\n}\nasync function writeAtomic(path, value) {\n\tconst temporary = join(dirname(path), `.${randomUUID()}.tmp`);\n\tconst handle = await open(temporary, \"wx\");\n\ttry {\n\t\tawait handle.writeFile(`${JSON.stringify(value, null, 2)}\\n`, \"utf8\");\n\t\tawait handle.sync();\n\t\tawait handle.close();\n\t\tawait rename(temporary, path);\n\t} finally {\n\t\tawait handle.close().catch(() => {});\n\t\tawait unlink(temporary).catch(() => {});\n\t}\n}\nasync function readJson(path) {\n\tawait assertRegular(path);\n\treturn JSON.parse(await readFile(path, \"utf8\"));\n}\n\n//#endregion\n//#region src/http.ts\nconst MAX_JSON_BYTES = 134217728;\nconst MAX_IMAGE_BYTES = 33554432;\nasync function readBounded(response, limit) {\n\tif (Number(response.headers.get(\"content-length\")) > limit) {\n\t\tawait response.body?.cancel();\n\t\tthrow new ImgRelayError(\"invalid_response\", \"上游响应超过大小限制\", 3);\n\t}\n\tif (!response.body) return Buffer.alloc(0);\n\tconst reader = response.body.getReader();\n\tconst chunks = [];\n\tlet size = 0;\n\ttry {\n\t\tfor (;;) {\n\t\t\tconst { value, done } = await reader.read();\n\t\t\tif (done) break;\n\t\t\tsize += value.byteLength;\n\t\t\tif (size > limit) throw new ImgRelayError(\"invalid_response\", \"上游响应超过大小限制\", 3);\n\t\t\tchunks.push(value);\n\t\t}\n\t\treturn Buffer.concat(chunks, size);\n\t} finally {\n\t\tawait reader.cancel().catch(() => {});\n\t\treader.releaseLock();\n\t}\n}\nfunction httpError(status, text, redactor) {\n\tlet detail = \"\";\n\ttry {\n\t\tconst parsed = JSON.parse(text);\n\t\tif (parsed && typeof parsed === \"object\" && \"error\" in parsed) {\n\t\t\tconst error = parsed.error;\n\t\t\tif (typeof error === \"string\") detail = error;\n\t\t\telse if (error && typeof error === \"object\" && \"message\" in error && typeof error.message === \"string\") detail = error.message;\n\t\t}\n\t} catch {}\n\tlet category = \"upstream_error\";\n\tif (status === 401 || status === 403) category = \"auth_error\";\n\telse if (status === 429) category = \"rate_limit\";\n\telse if (status === 402 || /insufficient.*(quota|balance)|余额不足/i.test(detail)) category = \"quota_exceeded\";\n\telse if (/model.*(not found|not exist|unavailable|invalid)|模型.*(不存在|不可用)/i.test(detail)) category = \"model_unavailable\";\n\telse if (/unsupported.*(param|size|quality|format)|unknown parameter|参数.*(不支持|无效)/i.test(detail)) category = \"parameter_unsupported\";\n\treturn new ImgRelayError(category, redactor.text(`上游返回 HTTP ${status}${detail ? `:${detail.slice(0, 1e3)}` : \",请检查接口、权限和请求参数\"}`), 3, status);\n}\nasync function requestJson(options) {\n\tconst method = options.method || \"GET\";\n\tconst attempts = method === \"GET\" && options.retry ? 2 : 1;\n\tfor (let attempt = 0; attempt < attempts; attempt++) {\n\t\tconst timeout = AbortSignal.timeout(Math.ceil((options.timeoutSeconds || 15) * 1e3));\n\t\tconst signal = options.signal ? AbortSignal.any([timeout, options.signal]) : timeout;\n\t\ttry {\n\t\t\tconst response = await fetch(options.url, {\n\t\t\t\tmethod,\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${options.key}`,\n\t\t\t\t\t...method === \"POST\" ? { \"Content-Type\": \"application/json\" } : {}\n\t\t\t\t},\n\t\t\t\t...options.body === void 0 ? {} : { body: JSON.stringify(options.body) },\n\t\t\t\tredirect: \"manual\",\n\t\t\t\tsignal\n\t\t\t});\n\t\t\tconst text = (await readBounded(response, response.ok ? MAX_JSON_BYTES : 65536)).toString(\"utf8\");\n\t\t\tif (!response.ok) throw httpError(response.status, text, options.redactor);\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(text);\n\t\t\t} catch {\n\t\t\t\tthrow new ImgRelayError(\"invalid_response\", \"上游成功响应不是有效 JSON\", 3);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (options.signal?.aborted) throw new ImgRelayError(\"interrupted\", method === \"POST\" ? \"已停止本地等待,无法保证取消已提交的上游生成\" : \"用户中断请求\", 130);\n\t\t\tconst retryable = !(error instanceof ImgRelayError) || error.httpStatus === 429 || error.httpStatus !== void 0 && error.httpStatus >= 500;\n\t\t\tif (attempt + 1 < attempts && retryable) {\n\t\t\t\tawait setTimeout(150);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (error instanceof ImgRelayError) throw error;\n\t\t\tthrow new ImgRelayError(method === \"POST\" ? \"result_unknown\" : \"upstream_error\", method === \"POST\" ? \"生成请求超时或网络断开,结果未知;上游可能仍在生成,请勿直接重复提交\" : \"模型查询超时或网络失败,请检查地址和网络\", 3);\n\t\t}\n\t}\n\tthrow new ImgRelayError(\"internal_error\", \"请求执行状态无效\", 1);\n}\n\n//#endregion\n//#region src/generate.ts\nfunction base64Bytes(value) {\n\tconst encoded = value.replace(/^data:image\\/[^;,]+;base64,/, \"\").replace(/\\s/g, \"\");\n\tif (encoded.length > Math.ceil(33554432 / 3) * 4 || !/^[A-Za-z0-9+/]+={0,2}$/.test(encoded) || encoded.length % 4 === 1) throw new ImgRelayError(\"image_decode_error\", \"Base64 图片无效或超过 32 MiB 限制\", 3);\n\tconst bytes = Buffer.from(encoded, \"base64\");\n\tif (bytes.length > 33554432 || bytes.toString(\"base64\").replace(/=+$/, \"\") !== encoded.replace(/=+$/, \"\")) throw new ImgRelayError(\"image_decode_error\", \"Base64 图片解码失败\", 3);\n\treturn bytes;\n}\nasync function download(urlString, signal) {\n\tlet current = urlString;\n\ttry {\n\t\tfor (let redirects = 0; redirects <= 3; redirects++) {\n\t\t\tconst url = new URL(current);\n\t\t\tif (![\"http:\", \"https:\"].includes(url.protocol) || url.username || url.password) throw new ImgRelayError(\"image_download_error\", \"图片地址必须为不含内嵌凭据的 HTTP(S) URL\", 3);\n\t\t\tconst timeout = AbortSignal.timeout(6e4);\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tredirect: \"manual\",\n\t\t\t\tsignal: signal ? AbortSignal.any([signal, timeout]) : timeout\n\t\t\t});\n\t\t\tif (response.status >= 300 && response.status < 400) {\n\t\t\t\tconst location = response.headers.get(\"location\");\n\t\t\t\tawait response.body?.cancel();\n\t\t\t\tif (!location) throw new ImgRelayError(\"image_download_error\", \"图片重定向缺少目标地址\", 3);\n\t\t\t\tcurrent = new URL(location, url).toString();\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!response.ok) {\n\t\t\t\tawait response.body?.cancel();\n\t\t\t\tthrow new ImgRelayError(\"image_download_error\", `图片下载返回 HTTP ${response.status}`, 3, response.status);\n\t\t\t}\n\t\t\treturn await readBounded(response, MAX_IMAGE_BYTES);\n\t\t}\n\t\tthrow new ImgRelayError(\"image_download_error\", \"图片下载重定向超过三次\", 3);\n\t} catch (error) {\n\t\tif (signal?.aborted) throw new ImgRelayError(\"interrupted\", \"已停止本地保存;无法保证取消已提交的上游生成\", 130);\n\t\tif (error instanceof ImgRelayError) throw error;\n\t\tthrow new ImgRelayError(\"image_download_error\", \"图片下载超时或网络失败;不会重新生成图片\", 3);\n\t}\n}\nfunction usageNumbers(value, depth = 0) {\n\tif (depth > 4) return void 0;\n\tif (typeof value === \"number\" && Number.isFinite(value)) return value;\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return void 0;\n\tconst entries = Object.entries(value).slice(0, 100).flatMap(([key, item]) => {\n\t\tif (!/^[a-z_][a-z0-9_]{0,63}$/i.test(key)) return [];\n\t\tconst result = usageNumbers(item, depth + 1);\n\t\treturn result === void 0 ? [] : [[key, result]];\n\t});\n\treturn entries.length ? Object.fromEntries(entries) : void 0;\n}\nasync function generate(store, options) {\n\tif (!options.prompt.trim()) throw new ImgRelayError(\"input_error\", \"提示词不能为空\");\n\tif (options.timeoutSeconds !== void 0 && (!Number.isFinite(options.timeoutSeconds) || options.timeoutSeconds <= 0 || options.timeoutSeconds > 2147483)) throw new ImgRelayError(\"input_error\", \"超时必须是有效的正数秒数\");\n\tif (options.filename && (basename(options.filename) !== options.filename || /[<>:\"/\\\\|?*]/.test(options.filename) || options.filename.split(\"\").some((character) => character.charCodeAt(0) < 32) || !parse(options.filename).name || [\".\", \"..\"].includes(options.filename))) throw new ImgRelayError(\"input_error\", \"--filename 必须是普通文件名,保存目录使用 --output-dir\");\n\tconst selected = await store.selected(options.provider);\n\tconst model = (options.model || selected.provider.defaultModel || \"\").trim();\n\tif (!model) throw new ImgRelayError(\"config_error\", \"未配置默认模型,请通过 --model 指定或运行 provider edit\");\n\tconst key = await store.key(selected.provider);\n\tconst outputDir = resolve(options.outputDir || \"output/imagegen\");\n\tconst requestId = randomUUID();\n\tconst recordPath = join(outputDir, `${requestId}-report.json`);\n\tconst supplied = {};\n\tfor (const name of [\n\t\t\"size\",\n\t\t\"n\",\n\t\t\"quality\",\n\t\t\"outputFormat\",\n\t\t\"responseFormat\"\n\t]) {\n\t\tconst value = options[name];\n\t\tif (value !== void 0) Object.assign(supplied, { [name]: value });\n\t}\n\tconst data = {\n\t\trequestId,\n\t\tprovider: selected.name,\n\t\trequestedModel: model,\n\t\trequestedCount: supplied.n || selected.provider.defaults.n || 1,\n\t\treturnedCount: 0,\n\t\tparameters: {\n\t\t\t...selected.provider.defaults,\n\t\t\t...supplied\n\t\t},\n\t\tendpoint: resolveEndpoint(selected.provider.baseUrl, selected.provider.endpoints.generate || \"/v1/images/generations\"),\n\t\tcapabilityEvidence: {\n\t\t\tknown: Object.hasOwn(KNOWN_MODEL_CAPABILITIES, model) ? KNOWN_MODEL_CAPABILITIES[model] || null : null,\n\t\t\tprovider: Object.hasOwn(selected.provider.modelOverrides, model) ? selected.provider.modelOverrides[model] || null : null\n\t\t},\n\t\timages: [],\n\t\tfailures: [],\n\t\trecordPath,\n\t\tsubmissionStatus: \"not_submitted\"\n\t};\n\tconst record = {\n\t\tschemaVersion: 1,\n\t\tcreatedAt: (/* @__PURE__ */ new Date()).toISOString(),\n\t\tprompt: options.prompt,\n\t\t...data\n\t};\n\ttry {\n\t\tawait mkdir(outputDir, { recursive: true });\n\t\tif (options.filename && !options.overwrite) try {\n\t\t\tawait access(join(outputDir, options.filename));\n\t\t\tthrow new ImgRelayError(\"save_error\", \"目标文件已存在,请使用其他文件名或显式 --overwrite\", 4);\n\t\t} catch (error) {\n\t\t\tif (!isNotFound(error)) throw error;\n\t\t}\n\t\tawait writeFile(recordPath, `${JSON.stringify(store.redactor.value({\n\t\t\t...record,\n\t\t\tstatus: \"prepared\"\n\t\t}), null, 2)}\\n`, {\n\t\t\tflag: \"wx\",\n\t\t\tmode: 384\n\t\t});\n\t} catch (error) {\n\t\tif (error instanceof ImgRelayError) throw error;\n\t\tthrow new ImgRelayError(\"save_error\", \"无法创建输出目录或请求记录;未提交生成请求\", 4);\n\t}\n\tlet outcome;\n\ttry {\n\t\tdata.parameters = resolveParameters(selected.provider, model, supplied);\n\t\tconst body = {\n\t\t\tmodel,\n\t\t\tprompt: options.prompt\n\t\t};\n\t\tfor (const [name, value] of Object.entries(data.parameters)) {\n\t\t\tconst wire = {\n\t\t\t\toutputFormat: \"output_format\",\n\t\t\t\tresponseFormat: \"response_format\"\n\t\t\t}[name] || name;\n\t\t\tbody[wire] = value;\n\t\t}\n\t\tif (options.signal?.aborted) throw new ImgRelayError(\"interrupted\", \"用户中断,未提交生成请求\", 130);\n\t\toptions.progress?.(\"正在等待生图接口,生成请求只提交一次…\");\n\t\tdata.submissionStatus = \"submitted\";\n\t\tconst response = await requestJson({\n\t\t\turl: data.endpoint,\n\t\t\tkey,\n\t\t\tredactor: store.redactor,\n\t\t\tmethod: \"POST\",\n\t\t\tbody,\n\t\t\ttimeoutSeconds: options.timeoutSeconds || selected.provider.timeoutSeconds,\n\t\t\t...options.signal ? { signal: options.signal } : {}\n\t\t});\n\t\tdata.submissionStatus = \"result_received\";\n\t\tif (!response || typeof response !== \"object\" || !(\"data\" in response) || !Array.isArray(response.data) || response.data.length === 0) throw new ImgRelayError(\"invalid_response\", \"上游响应没有有效的 data[] 图片结果\", 3);\n\t\tif (\"model\" in response && typeof response.model === \"string\") data.reportedModel = response.model;\n\t\tif (\"usage\" in response) {\n\t\t\tconst usage = usageNumbers(response.usage);\n\t\t\tif (usage !== void 0) data.usage = usage;\n\t\t}\n\t\tdata.returnedCount = response.data.length;\n\t\tfor (const [offset, item] of response.data.entries()) {\n\t\t\tconst index = offset + 1;\n\t\t\ttry {\n\t\t\t\tif (options.signal?.aborted) throw new ImgRelayError(\"interrupted\", \"用户中断保存,已保存的文件保持不变\", 130);\n\t\t\t\tif (!item || typeof item !== \"object\") throw new ImgRelayError(\"invalid_response\", \"图片条目不是对象\", 3);\n\t\t\t\tlet bytes;\n\t\t\t\tif (\"b64_json\" in item && typeof item.b64_json === \"string\" && item.b64_json) bytes = base64Bytes(item.b64_json);\n\t\t\t\telse if (\"url\" in item && typeof item.url === \"string\" && item.url) bytes = await download(item.url, options.signal);\n\t\t\t\telse throw new ImgRelayError(\"invalid_response\", \"图片条目缺少 b64_json 或 url\", 3);\n\t\t\t\tlet dimensions;\n\t\t\t\tlet format;\n\t\t\t\ttry {\n\t\t\t\t\tformat = await fileTypeFromBuffer(bytes);\n\t\t\t\t\tdimensions = imageSize(bytes);\n\t\t\t\t\tif (!format?.mime.startsWith(\"image/\") || !dimensions.width || !dimensions.height) throw new Error(\"Invalid image\");\n\t\t\t\t} catch {\n\t\t\t\t\tthrow new ImgRelayError(\"image_decode_error\", \"返回数据不是可识别的有效图片\", 3);\n\t\t\t\t}\n\t\t\t\tconst stem = options.filename ? parse(options.filename).name : requestId;\n\t\t\t\tconst sequence = !options.filename || response.data.length > 1 ? `-${String(index).padStart(2, \"0\")}` : \"\";\n\t\t\t\tconst path = join(outputDir, `${stem}${sequence}.${format.ext}`);\n\t\t\t\tconst handle = await open(path, options.overwrite ? \"w\" : \"wx\", 384).catch(() => {\n\t\t\t\t\tthrow new ImgRelayError(\"save_error\", \"无法保存图片;请检查文件重名和目录权限\", 4);\n\t\t\t\t});\n\t\t\t\ttry {\n\t\t\t\t\tawait handle.writeFile(bytes);\n\t\t\t\t\tawait handle.sync();\n\t\t\t\t} catch {\n\t\t\t\t\tawait handle.close().catch(() => {});\n\t\t\t\t\tawait unlink(path).catch(() => {});\n\t\t\t\t\tthrow new ImgRelayError(\"save_error\", \"图片写入失败;不会重新提交生成\", 4);\n\t\t\t\t} finally {\n\t\t\t\t\tawait handle.close().catch(() => {});\n\t\t\t\t}\n\t\t\t\tdata.images.push({\n\t\t\t\t\tindex,\n\t\t\t\t\tpath,\n\t\t\t\t\tformat: format.ext,\n\t\t\t\t\twidth: dimensions.width,\n\t\t\t\t\theight: dimensions.height,\n\t\t\t\t\tbytes: bytes.length\n\t\t\t\t});\n\t\t\t\toptions.progress?.(`已保存 ${index}/${data.returnedCount} 张图片`);\n\t\t\t} catch (error) {\n\t\t\t\tdata.failures.push({\n\t\t\t\t\tindex,\n\t\t\t\t\terror: store.redactor.error(error)\n\t\t\t\t});\n\t\t\t\tif (error instanceof ImgRelayError && error.category === \"interrupted\") throw error;\n\t\t\t}\n\t\t}\n\t\tconst failed = data.failures.length > 0;\n\t\tconst error = data.failures[0]?.error;\n\t\toutcome = data.images.length ? {\n\t\t\tstatus: failed ? \"partial_success\" : \"success\",\n\t\t\texitCode: failed ? 5 : 0,\n\t\t\tdata\n\t\t} : {\n\t\t\tstatus: \"error\",\n\t\t\texitCode: data.failures.some((failure) => failure.error.category === \"save_error\") ? 4 : 3,\n\t\t\tdata,\n\t\t\t...error ? { error } : {}\n\t\t};\n\t} catch (error) {\n\t\tconst info = store.redactor.error(error);\n\t\tif (info.category === \"result_unknown\") data.submissionStatus = \"unknown\";\n\t\toutcome = {\n\t\t\tstatus: info.category === \"result_unknown\" ? \"unknown\" : info.category === \"interrupted\" ? \"interrupted\" : \"error\",\n\t\t\texitCode: error instanceof ImgRelayError ? error.exitCode : 1,\n\t\t\tdata,\n\t\t\terror: info\n\t\t};\n\t}\n\ttry {\n\t\tawait writeAtomic(recordPath, store.redactor.value({\n\t\t\t...record,\n\t\t\t...data,\n\t\t\tstatus: outcome.status,\n\t\t\terror: outcome.error || null,\n\t\t\tcompletedAt: (/* @__PURE__ */ new Date()).toISOString()\n\t\t}));\n\t} catch {\n\t\tdata.recordPath = null;\n\t\treturn {\n\t\t\tstatus: \"error\",\n\t\t\texitCode: 4,\n\t\t\tdata,\n\t\t\terror: {\n\t\t\t\tcategory: \"save_error\",\n\t\t\t\tmessage: \"生成记录保存失败;已保存的图片路径仍可使用,不会重新生成\"\n\t\t\t}\n\t\t};\n\t}\n\treturn outcome;\n}\n\n//#endregion\n//#region src/models.ts\nconst modelsResponse = z.object({ data: z.array(z.object({\n\tid: z.string().min(1),\n\ttype: z.string().optional()\n})) });\nconst cachedModels = z.object({\n\tfetchedAt: z.iso.datetime(),\n\tmodels: modelsResponse.shape.data,\n\turl: z.string(),\n\trevision: z.number()\n});\nasync function discoverModels(provider, key, redactor, signal) {\n\tconst url = resolveEndpoint(provider.baseUrl, provider.endpoints.models || \"/v1/models\");\n\tconst response = modelsResponse.safeParse(await requestJson({\n\t\turl,\n\t\tkey,\n\t\tredactor,\n\t\tretry: true,\n\t\t...signal ? { signal } : {}\n\t}));\n\tif (!response.success) throw new ImgRelayError(\"invalid_response\", \"模型接口未返回 data[].id;仍可手动配置模型后生成\", 3);\n\treturn response.data.data;\n}\nasync function models(store, options = {}) {\n\tconst selected = await store.selected(options.provider);\n\tconst key = await store.key(selected.provider);\n\tconst url = resolveEndpoint(selected.provider.baseUrl, selected.provider.endpoints.models || \"/v1/models\");\n\tconst cacheKey = createHash(\"sha256\").update(JSON.stringify([\n\t\tselected.name,\n\t\turl,\n\t\tselected.provider.revision,\n\t\tkey\n\t])).digest(\"hex\");\n\tif (!options.refresh) {\n\t\tconst cache = z.record(z.string(), z.unknown()).safeParse(await store.cache());\n\t\tconst cached = cachedModels.safeParse(cache.success ? cache.data[cacheKey] : void 0);\n\t\tif (cached.success && Date.now() - Date.parse(cached.data.fetchedAt) >= 0 && Date.now() - Date.parse(cached.data.fetchedAt) < 9e5) return {\n\t\t\t...cached.data,\n\t\t\tprovider: selected.name,\n\t\t\tcached: true\n\t\t};\n\t}\n\tconst discovered = await discoverModels(selected.provider, key, store.redactor, options.signal);\n\tconst result = {\n\t\tfetchedAt: (/* @__PURE__ */ new Date()).toISOString(),\n\t\tmodels: discovered,\n\t\turl,\n\t\trevision: selected.provider.revision\n\t};\n\tawait store.saveCache(cacheKey, result);\n\treturn {\n\t\t...result,\n\t\tprovider: selected.name,\n\t\tcached: false\n\t};\n}\nasync function doctor(store, options = {}) {\n\tlet selected;\n\ttry {\n\t\tselected = await store.selected(options.provider);\n\t} catch (error) {\n\t\tconst info = store.redactor.error(error);\n\t\treturn {\n\t\t\texitCode: error instanceof ImgRelayError ? error.exitCode : 1,\n\t\t\terror: info,\n\t\t\tdata: {\n\t\t\t\tprovider: options.provider || null,\n\t\t\t\tendpoints: null,\n\t\t\t\tconfiguration: \"invalid\",\n\t\t\t\tauthentication: \"not_checked\",\n\t\t\t\tmodelDiscovery: { status: \"not_checked\" },\n\t\t\t\tgeneration: \"not_verified\"\n\t\t\t}\n\t\t};\n\t}\n\tconst endpoints = {\n\t\tgenerate: resolveEndpoint(selected.provider.baseUrl, selected.provider.endpoints.generate || \"/v1/images/generations\"),\n\t\tmodels: resolveEndpoint(selected.provider.baseUrl, selected.provider.endpoints.models || \"/v1/models\")\n\t};\n\ttry {\n\t\tconst result = await models(store, {\n\t\t\t...options,\n\t\t\trefresh: true\n\t\t});\n\t\treturn {\n\t\t\texitCode: 0,\n\t\t\tdata: {\n\t\t\t\tprovider: selected.name,\n\t\t\t\tendpoints,\n\t\t\t\tconfiguration: \"valid\",\n\t\t\t\tauthentication: \"verified_for_models\",\n\t\t\t\tmodelDiscovery: result,\n\t\t\t\tgeneration: \"not_verified\",\n\t\t\t\tdefaultModelListed: selected.provider.defaultModel ? result.models.some((model) => model.id === selected.provider.defaultModel) : null\n\t\t\t}\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof ImgRelayError && error.category === \"interrupted\") throw error;\n\t\tconst info = store.redactor.error(error);\n\t\treturn {\n\t\t\texitCode: error instanceof ImgRelayError ? error.exitCode : 1,\n\t\t\terror: info,\n\t\t\tdata: {\n\t\t\t\tprovider: selected.name,\n\t\t\t\tendpoints,\n\t\t\t\tconfiguration: \"valid\",\n\t\t\t\tauthentication: info.category === \"auth_error\" ? \"failed\" : \"unknown\",\n\t\t\t\tmodelDiscovery: {\n\t\t\t\t\tstatus: \"unavailable\",\n\t\t\t\t\terror: info\n\t\t\t\t},\n\t\t\t\tgeneration: \"not_verified\",\n\t\t\t\tmessage: \"模型列表不可用时,仍可手动设置模型;生成能力尚未验证\"\n\t\t\t}\n\t\t};\n\t}\n}\n\n//#endregion\n//#region src/store.ts\nfunction defaultConfigDirectory() {\n\tif (process.env.IMGRELAY_CONFIG_DIR) return resolve(process.env.IMGRELAY_CONFIG_DIR);\n\treturn join(homedir(), \".imgrelay\");\n}\nvar Store = class {\n\tdirectory;\n\tredactor = new Redactor();\n\tinitialized = false;\n\tconstructor(directory = defaultConfigDirectory()) {\n\t\tthis.directory = resolve(directory);\n\t\tif (this.directory === parse(this.directory).root) throw new ImgRelayError(\"config_error\", \"配置目录不能是文件系统根目录\");\n\t}\n\tasync config() {\n\t\ttry {\n\t\t\tconst raw = await readJson(join(this.directory, \"config.json\"));\n\t\t\tif (raw && typeof raw === \"object\" && \"schemaVersion\" in raw && raw.schemaVersion !== 1) throw new ImgRelayError(\"config_error\", \"不支持此配置版本;当前仅支持 schemaVersion=1\");\n\t\t\tconst result = configSchema.safeParse(raw);\n\t\t\tif (!result.success) throw new ImgRelayError(\"config_error\", \"配置文件结构或版本无效;请检查 config.json\");\n\t\t\tfor (const provider of Object.values(result.data.providers)) if (provider.apiKey) this.redactor.add(provider.apiKey);\n\t\t\treturn result.data;\n\t\t} catch (error) {\n\t\t\tif (isNotFound(error)) return {\n\t\t\t\tschemaVersion: 1,\n\t\t\t\tproviders: {}\n\t\t\t};\n\t\t\tif (error instanceof ImgRelayError) throw error;\n\t\t\tthrow new ImgRelayError(\"config_error\", \"无法读取配置文件;请检查文件格式及访问权限\");\n\t\t}\n\t}\n\tasync selected(name) {\n\t\tconst config = await this.config();\n\t\tconst selected = name || config.defaultProvider;\n\t\tif (!selected) throw new ImgRelayError(\"config_error\", \"未设置默认供应商,请运行 imgrelay provider use <名称>\");\n\t\tconst provider = Object.hasOwn(config.providers, selected) ? config.providers[selected] : void 0;\n\t\tif (!provider) throw new ImgRelayError(\"config_error\", `供应商 ${selected} 不存在,请运行 imgrelay provider add ${selected}`);\n\t\treturn {\n\t\t\tname: selected,\n\t\t\tprovider\n\t\t};\n\t}\n\tasync initialize() {\n\t\tif (!this.initialized) {\n\t\t\tawait mkdir(this.directory, { recursive: true });\n\t\t\tthis.initialized = true;\n\t\t}\n\t}\n\tasync locked(operation) {\n\t\tawait this.initialize();\n\t\tconst lock = join(this.directory, \".write-lock\");\n\t\tconst owner = join(lock, \"owner.json\");\n\t\tconst deadline = Date.now() + 1e4;\n\t\tfor (;;) try {\n\t\t\tawait mkdir(lock);\n\t\t\tbreak;\n\t\t} catch (error) {\n\t\t\tif (!(error instanceof Error && \"code\" in error && error.code === \"EEXIST\")) throw error;\n\t\t\ttry {\n\t\t\t\tconst data = z.object({ pid: z.number().int().positive() }).parse(await readJson(owner));\n\t\t\t\ttry {\n\t\t\t\t\tprocess.kill(data.pid, 0);\n\t\t\t\t} catch (checkError) {\n\t\t\t\t\tif (checkError instanceof Error && \"code\" in checkError && checkError.code === \"ESRCH\") {\n\t\t\t\t\t\tawait unlink(owner);\n\t\t\t\t\t\tawait rmdir(lock);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\ttry {\n\t\t\t\t\tif (Date.now() - (await lstat(lock)).mtimeMs > 6e4) {\n\t\t\t\t\t\tawait unlink(owner).catch(() => {});\n\t\t\t\t\t\tawait rmdir(lock);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t} catch {}\n\t\t\t}\n\t\t\tif (Date.now() >= deadline) throw new ImgRelayError(\"config_busy\", \"配置正在被其他进程修改,请稍后重试\");\n\t\t\tawait setTimeout(50);\n\t\t}\n\t\ttry {\n\t\t\tawait writeFile(owner, JSON.stringify({ pid: process.pid }));\n\t\t\treturn await operation();\n\t\t} finally {\n\t\t\tawait unlink(owner).catch(() => {});\n\t\t\tawait rmdir(lock).catch(() => {});\n\t\t}\n\t}\n\tasync key(provider) {\n\t\tconst key = provider.apiKey;\n\t\tif (!key) throw new ImgRelayError(\"credential_error\", \"未配置 API 密钥,请运行 imgrelay provider edit <名称>\");\n\t\tif (/[\\r\\n\\0]/.test(key)) throw new ImgRelayError(\"credential_error\", \"密钥不能包含换行或空字符\");\n\t\tthis.redactor.add(key);\n\t\treturn key;\n\t}\n\tasync put(name, input, options = {}) {\n\t\tif (!providerNameSchema.safeParse(name).success) throw new ImgRelayError(\"input_error\", \"供应商名称只能包含字母、数字、下划线和连字符\");\n\t\tif (input.apiKey) this.redactor.add(input.apiKey);\n\t\tif (options.secret) this.redactor.add(options.secret);\n\t\tconst proposed = parseProvider({\n\t\t\t...input,\n\t\t\t...options.secret !== void 0 ? { apiKey: options.secret } : {}\n\t\t});\n\t\tif (proposed.apiKey) this.redactor.add(proposed.apiKey);\n\t\treturn this.locked(async () => {\n\t\t\tconst config = await this.config();\n\t\t\tconst previous = Object.hasOwn(config.providers, name) ? config.providers[name] : void 0;\n\t\t\tif (options.edit ? !previous : previous) throw new ImgRelayError(\"config_error\", options.edit ? \"供应商不存在\" : \"供应商已存在,请使用 provider edit\");\n\t\t\tif (options.expectedRevision !== void 0 && previous?.revision !== options.expectedRevision) throw new ImgRelayError(\"config_busy\", \"配置已被其他进程修改,请重新执行编辑\");\n\t\t\tproposed.revision = (previous?.revision || 0) + 1;\n\t\t\tconfig.providers[name] = proposed;\n\t\t\tif (options.makeDefault) config.defaultProvider = name;\n\t\t\tawait writeAtomic(join(this.directory, \"config.json\"), config);\n\t\t\treturn proposed;\n\t\t});\n\t}\n\tasync use(name) {\n\t\tawait this.locked(async () => {\n\t\t\tconst config = await this.config();\n\t\t\tif (!Object.hasOwn(config.providers, name)) throw new ImgRelayError(\"config_error\", \"供应商不存在\");\n\t\t\tconfig.defaultProvider = name;\n\t\t\tawait writeAtomic(join(this.directory, \"config.json\"), config);\n\t\t});\n\t}\n\tasync remove(name) {\n\t\tawait this.locked(async () => {\n\t\t\tconst config = await this.config();\n\t\t\tif (!Object.hasOwn(config.providers, name)) throw new ImgRelayError(\"config_error\", \"供应商不存在\");\n\t\t\tdelete config.providers[name];\n\t\t\tif (config.defaultProvider === name) delete config.defaultProvider;\n\t\t\tawait writeAtomic(join(this.directory, \"config.json\"), config);\n\t\t});\n\t}\n\tasync cache() {\n\t\ttry {\n\t\t\treturn await readJson(join(this.directory, \"models-cache.json\"));\n\t\t} catch {\n\t\t\treturn {};\n\t\t}\n\t}\n\tasync saveCache(key, value) {\n\t\tawait this.locked(async () => {\n\t\t\tconst parsed = z.record(z.string(), z.unknown()).safeParse(await this.cache());\n\t\t\tconst cache = parsed.success ? parsed.data : {};\n\t\t\tcache[key] = value;\n\t\t\tconst entries = Object.entries(cache).slice(-100);\n\t\t\tawait writeAtomic(join(this.directory, \"models-cache.json\"), Object.fromEntries(entries));\n\t\t});\n\t}\n};\n\n//#endregion\nexport { CUBENCE_PRESET, ImgRelayError, KNOWN_MODEL_CAPABILITIES, Redactor, Store, configSchema, defaultConfigDirectory, discoverModels, doctor, generate, modelCapabilitySchema, models, normalizeBaseUrl, parseProvider, providerNameSchema, providerSchema, resolveEndpoint };\n//# sourceMappingURL=index.mjs.map","","/* Interactive prompts must be shown one at a time. */\n/* eslint-disable no-await-in-loop */\nimport { readFile } from 'node:fs/promises'\nimport { resolve } from 'node:path'\n\nimport * as prompts from '@clack/prompts'\nimport { CUBENCE_PRESET, discoverModels, ImgRelayError, parseProvider } from '@imgrelay/core'\nimport type { Provider, ProviderInput, Store } from '@imgrelay/core'\nimport type { Command } from 'commander'\n\nexport interface ProviderFlags {\n baseUrl?: string\n protocol?: string\n preset?: string\n model?: string\n clearKey?: boolean\n size?: string\n n?: string\n quality?: string\n outputFormat?: string\n responseFormat?: string\n generationPath?: string\n modelsPath?: string\n capabilitiesFile?: string\n timeout?: string\n default?: boolean\n}\n\nfunction answer(value: string | symbol): string\nfunction answer(value: boolean | symbol): boolean\nfunction answer(value: string | boolean | symbol): string | boolean {\n if (typeof value === 'symbol')\n throw new ImgRelayError('interrupted', '用户取消配置,未保存修改', 130)\n return value\n}\n\nexport function providerOptions(command: Command): Command {\n return command\n .option('--base-url <URL>', 'API 基础地址,推荐包含 /v1')\n .option('--protocol <协议>', '首版支持 openai-images')\n .option('--preset <名称>', '使用已验证配置预设:cubence')\n .option('--model <ID>', '默认模型,允许手动填写')\n .option('--clear-key', '清除配置中保存的密钥')\n .option('--default', '保存后设为默认供应商')\n .option('--size <尺寸>', '默认尺寸')\n .option('--n <数量>', '默认生成数量')\n .option('--quality <质量>', '默认质量')\n .option('--output-format <格式>', '默认图片格式')\n .option('--response-format <格式>', '供应商要求的返回格式:url 或 b64_json')\n .option('--generation-path <路径>', '生成端点覆盖')\n .option('--models-path <路径>', '模型端点覆盖')\n .option('--capabilities-file <文件>', '按模型的能力覆盖 JSON 文件')\n .option('--timeout <秒数>', '默认生成超时')\n}\n\nexport async function configureProvider(\n store: Store,\n name: string,\n flags: ProviderFlags,\n interactive: boolean,\n signal: AbortSignal,\n existing?: Provider,\n): Promise<Provider> {\n if (flags.preset && flags.preset !== 'cubence')\n throw new ImgRelayError('input_error', '未知预设;当前提供 cubence')\n if (!existing && !interactive)\n throw new ImgRelayError(\n 'config_error',\n '新增供应商需要隐藏输入 API 密钥,请在交互终端不带 --json 运行 provider add',\n )\n const input: ProviderInput = {\n protocol: 'openai-images',\n baseUrl: '',\n ...(flags.preset ? CUBENCE_PRESET : {}),\n ...existing,\n }\n if (flags.protocol) {\n if (flags.protocol !== 'openai-images')\n throw new ImgRelayError('config_error', '首版仅支持 openai-images 协议')\n input.protocol = flags.protocol\n }\n if (flags.baseUrl !== undefined) input.baseUrl = flags.baseUrl\n if (flags.model !== undefined) input.defaultModel = flags.model\n input.defaults = { ...input.defaults }\n input.endpoints = { ...input.endpoints }\n if (flags.size !== undefined) input.defaults.size = flags.size\n if (flags.n !== undefined) input.defaults.n = Number(flags.n)\n if (flags.quality !== undefined) input.defaults.quality = flags.quality\n if (flags.outputFormat !== undefined) input.defaults.outputFormat = flags.outputFormat\n if (flags.responseFormat !== undefined) {\n if (flags.responseFormat !== 'url' && flags.responseFormat !== 'b64_json')\n throw new ImgRelayError('input_error', '返回格式只能是 url 或 b64_json')\n input.defaults.responseFormat = flags.responseFormat\n }\n if (flags.generationPath !== undefined) input.endpoints.generate = flags.generationPath\n if (flags.modelsPath !== undefined) input.endpoints.models = flags.modelsPath\n if (flags.timeout !== undefined) input.timeoutSeconds = Number(flags.timeout)\n if (flags.capabilitiesFile) {\n try {\n const modelOverrides: unknown = JSON.parse(\n await readFile(resolve(flags.capabilitiesFile), 'utf8'),\n )\n input.modelOverrides = parseProvider({ ...input, modelOverrides }).modelOverrides\n } catch {\n throw new ImgRelayError('input_error', '能力覆盖文件必须是可读的 UTF-8 JSON')\n }\n }\n let secret: string | undefined\n if (flags.clearKey) delete input.apiKey\n if (interactive) {\n prompts.intro(existing ? `编辑供应商 ${name}` : `添加供应商 ${name}`)\n if (flags.baseUrl === undefined)\n input.baseUrl = answer(\n await prompts.text({\n message: 'API 基础地址',\n initialValue: input.baseUrl,\n validate: (value) => (value?.trim() ? undefined : '请输入地址'),\n }),\n )\n if (!flags.clearKey) {\n secret =\n answer(\n await prompts.password({\n message: input.apiKey ? 'API 密钥(留空保留当前密钥)' : 'API 密钥',\n validate: (value) => (value?.trim() || input.apiKey ? undefined : '密钥不能为空'),\n }),\n ).trim() || undefined\n if (secret) store.redactor.add(secret)\n }\n }\n if (!existing && !secret) throw new ImgRelayError('config_error', '新增供应商需要非空 API 密钥')\n if (interactive && flags.model === undefined) {\n let ids: string[] = []\n try {\n const key = secret || (await store.key(input))\n ids = (await discoverModels(parseProvider(input), key, store.redactor, signal)).map(\n (model) => model.id,\n )\n } catch (error) {\n if (error instanceof ImgRelayError && error.category === 'interrupted') throw error\n prompts.log.warn('未能查询模型列表,可以手动填写模型 ID;生成能力尚未验证')\n }\n const choice = ids.length\n ? answer(\n await prompts.select({\n message: '默认模型',\n options: [\n ...ids.map((id) => ({ value: id, label: store.redactor.text(id) })),\n { value: '\\0manual', label: '手动填写模型 ID' },\n ],\n }),\n )\n : '\\0manual'\n input.defaultModel =\n choice === '\\0manual'\n ? answer(\n await prompts.text({\n message: '默认模型(留空可稍后设置)',\n initialValue: input.defaultModel || '',\n }),\n )\n : choice\n if (!input.defaultModel) delete input.defaultModel\n }\n if (\n interactive &&\n answer(\n await prompts.confirm({\n message: '设置尺寸、数量、质量和格式的默认值?',\n initialValue: false,\n }),\n )\n ) {\n for (const [field, label] of [\n ['size', '尺寸'],\n ['n', '数量'],\n ['quality', '质量'],\n ['outputFormat', '图片格式'],\n ] as const) {\n const value = answer(\n await prompts.text({\n message: `${label}(留空表示不设置)`,\n initialValue: String(input.defaults[field] || ''),\n }),\n )\n if (value) Object.assign(input.defaults, { [field]: field === 'n' ? Number(value) : value })\n else delete input.defaults[field]\n }\n }\n const makeDefault =\n flags.default ||\n (interactive\n ? answer(\n await prompts.confirm({\n message: '设为默认供应商?',\n initialValue: !(await store.config()).defaultProvider,\n }),\n )\n : false)\n const saved = await store.put(name, input, {\n ...(existing ? { edit: true, expectedRevision: existing.revision } : {}),\n ...(secret ? { secret } : {}),\n makeDefault,\n })\n if (interactive) prompts.outro('配置已保存;此流程没有生成图片')\n return saved\n}\n","#!/usr/bin/env node\nimport { doctor, generate, ImgRelayError, models, Store } from '@imgrelay/core'\nimport type { ErrorInfo } from '@imgrelay/core'\nimport { Command, CommanderError } from 'commander'\n\nimport packageJson from '../package.json' with { type: 'json' }\nimport { configureProvider, providerOptions } from './provider.js'\nimport type { ProviderFlags } from './provider.js'\n\nconst json = process.argv.includes('--json')\nconst controller = new AbortController()\nprocess.once('SIGINT', () => controller.abort())\nprocess.once('SIGTERM', () => controller.abort())\nlet commandName = 'imgrelay'\nlet outputWritten = false\nlet helpOutput = ''\nlet store: Store | undefined\n\nfunction output(\n data: unknown,\n options: { status?: string; exitCode?: number; error?: ErrorInfo } = {},\n): void {\n if (outputWritten) return\n outputWritten = true\n const envelope = {\n schemaVersion: 1,\n command: commandName,\n status: options.status || 'success',\n data,\n error: options.error || null,\n }\n const safe = store ? store.redactor.value(envelope) : envelope\n if (json) process.stdout.write(`${JSON.stringify(safe)}\\n`)\n else {\n if (options.error)\n process.stderr.write(\n `${store?.redactor.text(options.error.message) || options.error.message}\\n`,\n )\n if (data !== null)\n process.stdout.write(\n `${JSON.stringify(store ? store.redactor.value(data) : data, null, 2)}\\n`,\n )\n }\n process.exitCode = options.exitCode || 0\n}\n\nfunction active(name: string): Store {\n commandName = name\n store ||= new Store()\n return store\n}\n\nconst program = new Command()\n .name('imgrelay')\n .description('通过统一入口调用 OpenAI Images 兼容中转站')\n .version(packageJson.version)\n .option('--json', '输出一个最终 JSON 对象,禁用交互输入')\n .exitOverride()\n .configureOutput({\n writeOut: (value) => {\n if (json) helpOutput += value\n else process.stdout.write(value)\n },\n writeErr: (value) => {\n if (!json) process.stderr.write(value)\n },\n })\n\nconst provider = program.command('provider').description('管理供应商配置与凭据')\nproviderOptions(provider.command('add <名称>').description('添加供应商')).action(\n async (name: string, flags: ProviderFlags) => {\n const current = active('provider add')\n const result = await configureProvider(\n current,\n name,\n flags,\n !json && process.stdin.isTTY && process.stdout.isTTY,\n controller.signal,\n )\n output({ provider: name, configuration: result })\n },\n)\nproviderOptions(provider.command('edit <名称>').description('修改供应商')).action(\n async (name: string, flags: ProviderFlags) => {\n const current = active('provider edit')\n const existing = await current.selected(name)\n const result = await configureProvider(\n current,\n name,\n flags,\n !json && process.stdin.isTTY && process.stdout.isTTY,\n controller.signal,\n existing.provider,\n )\n output({ provider: name, configuration: result })\n },\n)\nprovider\n .command('list')\n .description('列出供应商摘要')\n .action(async () => {\n const current = active('provider list')\n const config = await current.config()\n output({\n defaultProvider: config.defaultProvider || null,\n providers: Object.entries(config.providers).map(([name, entry]) => ({\n name,\n protocol: entry.protocol,\n baseUrl: entry.baseUrl,\n defaultModel: entry.defaultModel || null,\n credentialSource: entry.apiKey ? 'config' : null,\n default: name === config.defaultProvider,\n })),\n })\n })\nprovider\n .command('show <名称>')\n .description('查看脱敏配置')\n .action(async (name: string) => {\n const current = active('provider show')\n const selected = await current.selected(name)\n output({ provider: name, configuration: selected.provider })\n })\nprovider\n .command('use <名称>')\n .description('设置默认供应商')\n .action(async (name: string) => {\n const current = active('provider use')\n await current.use(name)\n output({ defaultProvider: name })\n })\nprovider\n .command('remove <名称>')\n .description('移除供应商及其已保存的密钥')\n .action(async (name: string) => {\n const current = active('provider remove')\n await current.remove(name)\n output({ removed: name })\n })\nprogram\n .command('models')\n .description('查询模型列表或查看 15 分钟缓存')\n .option('--provider <名称>', '本次使用的供应商')\n .option('--refresh', '强制刷新模型列表')\n .action(async (flags: { provider?: string; refresh?: boolean }) => {\n const current = active('models')\n output(await models(current, { ...flags, signal: controller.signal }))\n })\nprogram\n .command('doctor')\n .description('检查配置与模型接口,不生成图片')\n .option('--provider <名称>', '检查指定供应商')\n .action(async (flags: { provider?: string }) => {\n const current = active('doctor')\n const result = await doctor(current, { ...flags, signal: controller.signal })\n output(result.data, {\n status: result.exitCode ? 'error' : 'success',\n exitCode: result.exitCode,\n ...(result.error ? { error: result.error } : {}),\n })\n })\nprogram\n .command('generate')\n .description('生成图片并保存原图和记录')\n .option('--prompt <文本>', '直接提供非空提示词(必填)')\n .option('--provider <名称>', '本次使用的供应商')\n .option('--model <ID>', '本次使用的模型')\n .option('--size <尺寸>', '图片尺寸,如 auto 或 1024x1024')\n .option('--n <数量>', '请求图片数量,不自动拆单')\n .option('--quality <质量>', '请求质量')\n .option('--output-format <格式>', '请求图片格式')\n .option('--output-dir <目录>', '保存目录,默认 output/imagegen')\n .option('--filename <名称>', '文件名;多图追加序号,扩展名按实际格式')\n .option('--overwrite', '允许覆盖图片文件')\n .option('--timeout <秒数>', '生成等待超时,默认 600 秒')\n .action(\n async (flags: {\n prompt?: string\n provider?: string\n model?: string\n size?: string\n n?: string\n quality?: string\n outputFormat?: string\n outputDir?: string\n filename?: string\n overwrite?: boolean\n timeout?: string\n }) => {\n const current = active('generate')\n if (flags.prompt === undefined)\n throw new ImgRelayError('input_error', '请通过 --prompt 提供非空提示词')\n const result = await generate(current, {\n prompt: flags.prompt,\n ...(flags.provider ? { provider: flags.provider } : {}),\n ...(flags.model ? { model: flags.model } : {}),\n ...(flags.size !== undefined ? { size: flags.size } : {}),\n ...(flags.n !== undefined ? { n: Number(flags.n) } : {}),\n ...(flags.quality !== undefined ? { quality: flags.quality } : {}),\n ...(flags.outputFormat !== undefined ? { outputFormat: flags.outputFormat } : {}),\n ...(flags.outputDir !== undefined ? { outputDir: flags.outputDir } : {}),\n ...(flags.filename !== undefined ? { filename: flags.filename } : {}),\n ...(flags.timeout !== undefined ? { timeoutSeconds: Number(flags.timeout) } : {}),\n overwrite: Boolean(flags.overwrite),\n signal: controller.signal,\n progress: (message) => process.stderr.write(`${message}\\n`),\n })\n output(result.data, {\n status: result.status,\n exitCode: result.exitCode,\n ...(result.error ? { error: result.error } : {}),\n })\n },\n )\nprogram.action(() => {\n if (json) output({ help: program.helpInformation() })\n else program.outputHelp()\n})\n\ntry {\n await program.parseAsync(process.argv)\n} catch (error) {\n if (error instanceof CommanderError && error.exitCode === 0) {\n if (json) output({ help: helpOutput.trim() })\n process.exitCode = 0\n } else {\n const failure =\n error instanceof CommanderError ? new ImgRelayError('input_error', error.message) : error\n const info: ErrorInfo = store\n ? store.redactor.error(failure)\n : {\n category: failure instanceof ImgRelayError ? failure.category : 'internal_error',\n message: failure instanceof Error ? failure.message : '发生未知错误',\n }\n output(null, {\n status: info.category === 'interrupted' ? 'interrupted' : 'error',\n exitCode: failure instanceof ImgRelayError ? failure.exitCode : 1,\n error: info,\n })\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["packageJson.version"],"sources":["../../core/dist/index.mjs","../package.json","../src/prompt.ts","../src/provider.ts","../src/index.ts"],"sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport { access, lstat, mkdir, open, readFile, rename, rmdir, unlink, writeFile } from \"node:fs/promises\";\nimport { basename, dirname, join, parse, resolve } from \"node:path\";\nimport { fileTypeFromBuffer } from \"file-type\";\nimport { imageSize } from \"image-size\";\nimport { setTimeout } from \"node:timers/promises\";\nimport { z } from \"zod\";\nimport { homedir } from \"node:os\";\n\n//#region src/errors.ts\nvar ImgRelayError = class extends Error {\n\tcategory;\n\texitCode;\n\thttpStatus;\n\tconstructor(category, message, exitCode = 2, httpStatus) {\n\t\tsuper(message);\n\t\tthis.name = \"ImgRelayError\";\n\t\tthis.category = category;\n\t\tthis.exitCode = exitCode;\n\t\tthis.httpStatus = httpStatus;\n\t}\n};\n/** Redact before serialization; never retain an upstream response as a diagnostic. */\nvar Redactor = class {\n\tsecrets = /* @__PURE__ */ new Set();\n\tadd(secret) {\n\t\tif (secret) this.secrets.add(secret);\n\t}\n\ttext(value) {\n\t\tlet text = value;\n\t\tfor (const secret of [...this.secrets].toSorted((a, b) => b.length - a.length)) text = text.replaceAll(secret, \"[REDACTED]\");\n\t\treturn text.replace(/https?:\\/\\/[^\\s<>\"']+/gi, (raw) => {\n\t\t\ttry {\n\t\t\t\tconst url = new URL(raw);\n\t\t\t\tif (url.username || url.password) {\n\t\t\t\t\turl.username = \"REDACTED\";\n\t\t\t\t\turl.password = \"\";\n\t\t\t\t}\n\t\t\t\tif (url.search) url.search = \"?REDACTED\";\n\t\t\t\tif (url.hash) url.hash = \"#REDACTED\";\n\t\t\t\treturn url.toString();\n\t\t\t} catch {\n\t\t\t\treturn \"[REDACTED_URL]\";\n\t\t\t}\n\t\t});\n\t}\n\tvalue(value) {\n\t\tif (typeof value === \"string\") return this.text(value);\n\t\tif (Array.isArray(value)) return value.map((item) => this.value(item));\n\t\tif (value && typeof value === \"object\") return Object.fromEntries(Object.entries(value).map(([key, item]) => [this.text(key), key === \"promptSha256\" && typeof item === \"string\" && /^[a-f0-9]{64}$/.test(item) ? item : this.value(item)]));\n\t\treturn value;\n\t}\n\terror(error) {\n\t\tif (error instanceof ImgRelayError) return {\n\t\t\tcategory: error.category,\n\t\t\tmessage: this.text(error.message),\n\t\t\t...error.httpStatus === void 0 ? {} : { httpStatus: error.httpStatus }\n\t\t};\n\t\treturn {\n\t\t\tcategory: \"internal_error\",\n\t\t\tmessage: this.text(error instanceof Error ? error.message : \"发生未知错误\")\n\t\t};\n\t}\n};\n\n//#endregion\n//#region src/files.ts\nfunction isNotFound(error) {\n\treturn error instanceof Error && \"code\" in error && error.code === \"ENOENT\";\n}\nasync function assertRegular(path) {\n\tconst stat = await lstat(path);\n\tif (!stat.isFile() || stat.isSymbolicLink()) throw new ImgRelayError(\"credential_error\", \"配置或凭据文件必须是普通文件,不能使用符号链接\");\n}\nasync function writeAtomic(path, value) {\n\tconst temporary = join(dirname(path), `.${randomUUID()}.tmp`);\n\tconst handle = await open(temporary, \"wx\");\n\ttry {\n\t\tawait handle.writeFile(`${JSON.stringify(value, null, 2)}\\n`, \"utf8\");\n\t\tawait handle.sync();\n\t\tawait handle.close();\n\t\tawait rename(temporary, path);\n\t} finally {\n\t\tawait handle.close().catch(() => {});\n\t\tawait unlink(temporary).catch(() => {});\n\t}\n}\nasync function readJson(path) {\n\tawait assertRegular(path);\n\treturn JSON.parse(await readFile(path, \"utf8\"));\n}\n\n//#endregion\n//#region src/http.ts\nconst MAX_JSON_BYTES = 134217728;\nconst MAX_IMAGE_BYTES = 33554432;\nasync function readBounded(response, limit) {\n\tif (Number(response.headers.get(\"content-length\")) > limit) {\n\t\tawait response.body?.cancel();\n\t\tthrow new ImgRelayError(\"invalid_response\", \"上游响应超过大小限制\", 3);\n\t}\n\tif (!response.body) return Buffer.alloc(0);\n\tconst reader = response.body.getReader();\n\tconst chunks = [];\n\tlet size = 0;\n\ttry {\n\t\tfor (;;) {\n\t\t\tconst { value, done } = await reader.read();\n\t\t\tif (done) break;\n\t\t\tsize += value.byteLength;\n\t\t\tif (size > limit) throw new ImgRelayError(\"invalid_response\", \"上游响应超过大小限制\", 3);\n\t\t\tchunks.push(value);\n\t\t}\n\t\treturn Buffer.concat(chunks, size);\n\t} finally {\n\t\tawait reader.cancel().catch(() => {});\n\t\treader.releaseLock();\n\t}\n}\nfunction httpError(status, text, redactor) {\n\tlet detail = \"\";\n\ttry {\n\t\tconst parsed = JSON.parse(text);\n\t\tif (parsed && typeof parsed === \"object\" && \"error\" in parsed) {\n\t\t\tconst error = parsed.error;\n\t\t\tif (typeof error === \"string\") detail = error;\n\t\t\telse if (error && typeof error === \"object\" && \"message\" in error && typeof error.message === \"string\") detail = error.message;\n\t\t}\n\t} catch {}\n\tlet category = \"upstream_error\";\n\tif (status === 401 || status === 403) category = \"auth_error\";\n\telse if (status === 429) category = \"rate_limit\";\n\telse if (status === 402 || /insufficient.*(quota|balance)|余额不足/i.test(detail)) category = \"quota_exceeded\";\n\telse if (/model.*(not found|not exist|unavailable|invalid)|模型.*(不存在|不可用)/i.test(detail)) category = \"model_unavailable\";\n\telse if (/unsupported.*(param|size|quality|format)|unknown parameter|参数.*(不支持|无效)/i.test(detail)) category = \"parameter_unsupported\";\n\treturn new ImgRelayError(category, redactor.text(`上游返回 HTTP ${status}${detail ? `:${detail.slice(0, 1e3)}` : \",请检查接口、权限和请求参数\"}`), 3, status);\n}\nasync function requestJson(options) {\n\tconst method = options.method || \"GET\";\n\tconst attempts = method === \"GET\" && options.retry ? 2 : 1;\n\tfor (let attempt = 0; attempt < attempts; attempt++) {\n\t\tconst timeout = AbortSignal.timeout(Math.ceil((options.timeoutSeconds || 15) * 1e3));\n\t\tconst signal = options.signal ? AbortSignal.any([timeout, options.signal]) : timeout;\n\t\ttry {\n\t\t\tconst response = await fetch(options.url, {\n\t\t\t\tmethod,\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${options.key}`,\n\t\t\t\t\t...method === \"POST\" ? { \"Content-Type\": \"application/json\" } : {}\n\t\t\t\t},\n\t\t\t\t...options.body === void 0 ? {} : { body: JSON.stringify(options.body) },\n\t\t\t\tredirect: \"manual\",\n\t\t\t\tsignal\n\t\t\t});\n\t\t\tconst text = (await readBounded(response, response.ok ? MAX_JSON_BYTES : 65536)).toString(\"utf8\");\n\t\t\tif (!response.ok) throw httpError(response.status, text, options.redactor);\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(text);\n\t\t\t} catch {\n\t\t\t\tthrow new ImgRelayError(\"invalid_response\", \"上游成功响应不是有效 JSON\", 3);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (options.signal?.aborted) throw new ImgRelayError(\"interrupted\", method === \"POST\" ? \"已停止本地等待,无法保证取消已提交的上游生成\" : \"用户中断请求\", 130);\n\t\t\tconst retryable = !(error instanceof ImgRelayError) || error.httpStatus === 429 || error.httpStatus !== void 0 && error.httpStatus >= 500;\n\t\t\tif (attempt + 1 < attempts && retryable) {\n\t\t\t\tawait setTimeout(150);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (error instanceof ImgRelayError) throw error;\n\t\t\tthrow new ImgRelayError(method === \"POST\" ? \"result_unknown\" : \"upstream_error\", method === \"POST\" ? \"生成请求超时或网络断开,结果未知;上游可能仍在生成,请勿直接重复提交\" : \"模型查询超时或网络失败,请检查地址和网络\", 3);\n\t\t}\n\t}\n\tthrow new ImgRelayError(\"internal_error\", \"请求执行状态无效\", 1);\n}\n\n//#endregion\n//#region src/urls.ts\nfunction parseApiUrl(value) {\n\tlet url;\n\ttry {\n\t\turl = new URL(value);\n\t} catch {\n\t\tthrow new ImgRelayError(\"config_error\", \"API 地址必须是完整的 HTTP 或 HTTPS URL\");\n\t}\n\tif (![\"http:\", \"https:\"].includes(url.protocol) || url.username || url.password || url.search || url.hash) throw new ImgRelayError(\"config_error\", \"API 地址只能使用 HTTP(S),不能包含凭据、查询参数或片段\");\n\treturn url;\n}\nfunction normalizeBaseUrl(value) {\n\treturn normalizeAddress(value).baseUrl;\n}\nfunction normalizeAddress(value) {\n\tconst url = parseApiUrl(value);\n\tconst path = url.pathname.replace(/\\/+$/, \"\");\n\tconst isGeneration = path.endsWith(\"/images/generations\");\n\turl.pathname = isGeneration ? path.slice(0, -19) : path;\n\treturn {\n\t\tbaseUrl: url.toString().replace(/\\/+$/, \"\"),\n\t\t...isGeneration ? { generationPath: \"/images/generations\" } : {}\n\t};\n}\nfunction validateEndpoint(path) {\n\ttry {\n\t\treturn path.startsWith(\"/\") && !/[?#\\\\]/.test(path) && !path.includes(\"//\") && !path.split(\"/\").some((part) => [\"..\", \".\"].includes(decodeURIComponent(part)));\n\t} catch {\n\t\treturn false;\n\t}\n}\nfunction resolveEndpoint(baseUrl, endpoint) {\n\tif (!validateEndpoint(endpoint)) throw new ImgRelayError(\"config_error\", \"端点必须是路径,不能包含主机、查询参数或上级目录\");\n\tconst url = parseApiUrl(baseUrl);\n\tconst basePath = url.pathname.replace(/\\/+$/, \"\");\n\turl.pathname = `${basePath}${basePath.endsWith(\"/v1\") && endpoint.startsWith(\"/v1/\") ? endpoint.slice(3) : endpoint}`;\n\treturn url.toString();\n}\n\n//#endregion\n//#region src/schema.ts\nconst shortText = z.string().trim().min(1).max(256);\nconst providerNameSchema = z.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/);\nconst parameterSchema = z.strictObject({\n\tsize: shortText.optional(),\n\tn: z.number().int().positive().optional(),\n\tquality: shortText.optional(),\n\toutputFormat: shortText.optional(),\n\tresponseFormat: z.enum([\"url\", \"b64_json\"]).optional()\n});\nconst parameterCapabilitySchema = z.strictObject({\n\tsupported: z.boolean().optional(),\n\tvalues: z.array(shortText).min(1).optional(),\n\tmin: z.number().optional(),\n\tmax: z.number().optional()\n});\nconst modelCapabilitySchema = z.strictObject({\n\tsource: z.enum([\n\t\t\"official_documentation\",\n\t\t\"provider_override\",\n\t\t\"call_verification\"\n\t]).default(\"provider_override\"),\n\tsourceUrl: z.url().optional(),\n\tverifiedAt: z.iso.datetime().optional(),\n\tparameters: z.strictObject({\n\t\tsize: parameterCapabilitySchema.optional(),\n\t\tn: parameterCapabilitySchema.optional(),\n\t\tquality: parameterCapabilitySchema.optional(),\n\t\toutputFormat: parameterCapabilitySchema.optional(),\n\t\tresponseFormat: parameterCapabilitySchema.optional()\n\t})\n});\nconst endpointSchema = z.string().max(1024).refine((value) => {\n\ttry {\n\t\treturn validateEndpoint(value);\n\t} catch {\n\t\treturn false;\n\t}\n}, \"端点必须是有效路径\");\nconst providerSchema = z.strictObject({\n\tprotocol: z.literal(\"openai-images\"),\n\tbaseUrl: z.string(),\n\tapiKey: z.string().trim().min(1).refine((key) => !/[\\r\\n\\0]/.test(key), \"密钥不能包含换行或空字符\").optional(),\n\tdefaultModel: shortText.optional(),\n\tdefaults: parameterSchema.default({}),\n\tendpoints: z.strictObject({\n\t\tgenerate: endpointSchema.optional(),\n\t\tmodels: endpointSchema.optional()\n\t}).default({}),\n\tmodelOverrides: z.record(shortText, modelCapabilitySchema).default({}),\n\ttimeoutSeconds: z.number().positive().max(2147483).finite().default(600),\n\trevision: z.number().int().positive().default(1)\n}).transform((provider) => {\n\tconst address = normalizeAddress(provider.baseUrl);\n\treturn {\n\t\t...provider,\n\t\tbaseUrl: address.baseUrl,\n\t\tendpoints: address.generationPath && !provider.endpoints.generate ? {\n\t\t\t...provider.endpoints,\n\t\t\tgenerate: address.generationPath\n\t\t} : provider.endpoints\n\t};\n});\nconst configSchema = z.strictObject({\n\tschemaVersion: z.literal(1),\n\tdefaultProvider: providerNameSchema.optional(),\n\tproviders: z.record(providerNameSchema, providerSchema)\n});\nfunction parseProvider(input) {\n\tconst result = providerSchema.safeParse(input);\n\tif (!result.success) throw new ImgRelayError(\"config_error\", `供应商配置无效:${result.error.issues.map((issue) => `${issue.path.join(\".\")} ${issue.message}`).join(\";\")}`);\n\treturn result.data;\n}\nconst CUBENCE_PRESET = {\n\tprotocol: \"openai-images\",\n\tbaseUrl: \"https://api-lb.cubence.ai/v1\",\n\tdefaultModel: \"gpt-image-2.5-flare\",\n\tdefaults: {\n\t\tsize: \"auto\",\n\t\tn: 1,\n\t\tquality: \"high\",\n\t\toutputFormat: \"png\"\n\t}\n};\n\n//#endregion\n//#region src/capabilities.ts\nconst GPT_IMAGE_CAPABILITY = {\n\tsource: \"official_documentation\",\n\tsourceUrl: \"https://developers.openai.com/api/reference/python/resources/images/methods/generate\",\n\tverifiedAt: \"2026-10-10T10:03:00.000Z\",\n\tparameters: {\n\t\tn: {\n\t\t\tmin: 1,\n\t\t\tmax: 10\n\t\t},\n\t\tsize: { values: [\n\t\t\t\"auto\",\n\t\t\t\"1024x1024\",\n\t\t\t\"1536x1024\",\n\t\t\t\"1024x1536\"\n\t\t] },\n\t\tquality: { values: [\n\t\t\t\"auto\",\n\t\t\t\"low\",\n\t\t\t\"medium\",\n\t\t\t\"high\"\n\t\t] },\n\t\toutputFormat: { values: [\n\t\t\t\"png\",\n\t\t\t\"jpeg\",\n\t\t\t\"webp\"\n\t\t] },\n\t\tresponseFormat: { supported: false }\n\t}\n};\nconst KNOWN_MODEL_CAPABILITIES = {\n\t\"gpt-image-1\": GPT_IMAGE_CAPABILITY,\n\t\"gpt-image-1-mini\": GPT_IMAGE_CAPABILITY\n};\nfunction resolveParameters(provider, model, supplied) {\n\tconst parsed = parameterSchema.safeParse({\n\t\tn: 1,\n\t\t...provider.defaults,\n\t\t...supplied\n\t});\n\tif (!parsed.success) throw new ImgRelayError(\"input_error\", \"生成参数无效:数量必须是正整数,各参数必须是非空字符串\");\n\tconst result = parsed.data;\n\tconst known = Object.hasOwn(KNOWN_MODEL_CAPABILITIES, model) ? KNOWN_MODEL_CAPABILITIES[model] : void 0;\n\tconst override = Object.hasOwn(provider.modelOverrides, model) ? provider.modelOverrides[model] : void 0;\n\tconst limits = {\n\t\t...known?.parameters,\n\t\t...override?.parameters\n\t};\n\tfor (const name of [\n\t\t\"size\",\n\t\t\"n\",\n\t\t\"quality\",\n\t\t\"outputFormat\",\n\t\t\"responseFormat\"\n\t]) {\n\t\tconst value = result[name];\n\t\tconst limit = limits[name];\n\t\tif (value === void 0 || !limit) continue;\n\t\tif (limit.supported === false && name === \"n\" && supplied.n === void 0 && provider.defaults.n === void 0) {\n\t\t\tdelete result.n;\n\t\t\tcontinue;\n\t\t}\n\t\tif (limit.supported === false || limit.values && !limit.values.includes(String(value)) || typeof value === \"number\" && (limit.min !== void 0 && value < limit.min || limit.max !== void 0 && value > limit.max)) throw new ImgRelayError(\"parameter_unsupported\", `模型 ${model} 不支持参数 ${name}=${value};请检查模型能力或供应商覆盖`, 2);\n\t}\n\treturn result;\n}\n\n//#endregion\n//#region src/request.ts\nconst parameterNames = [\n\t\"size\",\n\t\"n\",\n\t\"quality\",\n\t\"outputFormat\",\n\t\"responseFormat\"\n];\n/** Resolve local configuration without requiring credentials, network or filesystem writes. */\nasync function prepareRequest(store, options) {\n\tif (!options.prompt.trim()) throw new ImgRelayError(\"input_error\", \"提示词不能为空\");\n\tfor (const name of [\n\t\t\"provider\",\n\t\t\"model\",\n\t\t\"outputDir\"\n\t]) if (options[name] !== void 0 && !options[name].trim()) throw new ImgRelayError(\"input_error\", `${name} 不能为空`);\n\tif (options.timeoutSeconds !== void 0 && (!Number.isFinite(options.timeoutSeconds) || options.timeoutSeconds <= 0 || options.timeoutSeconds > 2147483)) throw new ImgRelayError(\"input_error\", \"超时必须是有效的正数秒数\");\n\tif (options.filename !== void 0 && (!options.filename || basename(options.filename) !== options.filename || /[<>:\"/\\\\|?*]/.test(options.filename) || options.filename.split(\"\").some((character) => character.charCodeAt(0) < 32) || !parse(options.filename).name || [\".\", \"..\"].includes(options.filename))) throw new ImgRelayError(\"input_error\", \"--filename 必须是普通文件名,保存目录使用 --output-dir\");\n\tconst selected = await store.selected(options.provider);\n\tconst model = (options.model ?? selected.provider.defaultModel ?? \"\").trim();\n\tif (!model) throw new ImgRelayError(\"config_error\", \"未配置默认模型,请通过 --model 指定或运行 provider edit\");\n\tconst supplied = {};\n\tconst parameterSources = {};\n\tfor (const name of parameterNames) {\n\t\tconst value = options[name];\n\t\tif (value !== void 0) Object.assign(supplied, { [name]: value });\n\t\tif (value !== void 0) parameterSources[name] = \"explicit\";\n\t\telse if (selected.provider.defaults[name] !== void 0) parameterSources[name] = \"provider_default\";\n\t\telse if (name === \"n\") parameterSources.n = \"tool_default\";\n\t}\n\treturn {\n\t\tdetails: {\n\t\t\tpromptSource: options.promptSource ?? { type: \"api\" },\n\t\t\tpromptSha256: createHash(\"sha256\").update(options.prompt, \"utf8\").digest(\"hex\"),\n\t\t\tpromptCharacters: options.prompt.length,\n\t\t\tpromptUtf8Bytes: Buffer.byteLength(options.prompt, \"utf8\"),\n\t\t\tprovider: selected.name,\n\t\t\trequestedModel: model,\n\t\t\tparameters: {\n\t\t\t\tn: 1,\n\t\t\t\t...selected.provider.defaults,\n\t\t\t\t...supplied\n\t\t\t},\n\t\t\tendpoint: resolveEndpoint(selected.provider.baseUrl, selected.provider.endpoints.generate || \"/v1/images/generations\"),\n\t\t\tcapabilityEvidence: {\n\t\t\t\tknown: Object.hasOwn(KNOWN_MODEL_CAPABILITIES, model) ? KNOWN_MODEL_CAPABILITIES[model] || null : null,\n\t\t\t\tprovider: Object.hasOwn(selected.provider.modelOverrides, model) ? selected.provider.modelOverrides[model] || null : null\n\t\t\t},\n\t\t\toutputDir: resolve(options.outputDir ?? \"output/imagegen\"),\n\t\t\tfilename: options.filename ?? null,\n\t\t\toverwrite: Boolean(options.overwrite),\n\t\t\ttimeoutSeconds: options.timeoutSeconds ?? selected.provider.timeoutSeconds,\n\t\t\tsources: {\n\t\t\t\tprovider: options.provider !== void 0 ? \"explicit\" : \"default\",\n\t\t\t\tmodel: options.model !== void 0 ? \"explicit\" : \"provider_default\",\n\t\t\t\tparameters: parameterSources,\n\t\t\t\toutputDir: options.outputDir !== void 0 ? \"explicit\" : \"tool_default\",\n\t\t\t\tfilename: options.filename !== void 0 ? \"explicit\" : \"tool_default\",\n\t\t\t\toverwrite: options.overwrite ? \"explicit\" : \"tool_default\",\n\t\t\t\ttimeoutSeconds: options.timeoutSeconds !== void 0 ? \"explicit\" : \"provider_default\"\n\t\t\t}\n\t\t},\n\t\tprovider: selected.provider,\n\t\tsupplied\n\t};\n}\nfunction validateRequest(prepared) {\n\tprepared.details.parameters = resolveParameters(prepared.provider, prepared.details.requestedModel, prepared.supplied);\n\tfor (const name of parameterNames) if (prepared.details.parameters[name] === void 0) delete prepared.details.sources.parameters[name];\n}\nasync function previewGenerate(store, options) {\n\tconst prepared = await prepareRequest(store, options);\n\tvalidateRequest(prepared);\n\tif (options.signal?.aborted) throw new ImgRelayError(\"interrupted\", \"用户中断,未提交生成请求\", 130);\n\treturn {\n\t\t...prepared.details,\n\t\tdryRun: true,\n\t\tcredentialConfigured: Boolean(prepared.provider.apiKey),\n\t\tsubmissionStatus: \"not_submitted\",\n\t\twillSubmitNetworkRequest: false\n\t};\n}\n\n//#endregion\n//#region src/generate.ts\nfunction base64Bytes(value) {\n\tconst encoded = value.replace(/^data:image\\/[^;,]+;base64,/, \"\").replace(/\\s/g, \"\");\n\tif (encoded.length > Math.ceil(33554432 / 3) * 4 || !/^[A-Za-z0-9+/]+={0,2}$/.test(encoded) || encoded.length % 4 === 1) throw new ImgRelayError(\"image_decode_error\", \"Base64 图片无效或超过 32 MiB 限制\", 3);\n\tconst bytes = Buffer.from(encoded, \"base64\");\n\tif (bytes.length > 33554432 || bytes.toString(\"base64\").replace(/=+$/, \"\") !== encoded.replace(/=+$/, \"\")) throw new ImgRelayError(\"image_decode_error\", \"Base64 图片解码失败\", 3);\n\treturn bytes;\n}\nasync function download(urlString, signal) {\n\tlet current = urlString;\n\ttry {\n\t\tfor (let redirects = 0; redirects <= 3; redirects++) {\n\t\t\tconst url = new URL(current);\n\t\t\tif (![\"http:\", \"https:\"].includes(url.protocol) || url.username || url.password) throw new ImgRelayError(\"image_download_error\", \"图片地址必须为不含内嵌凭据的 HTTP(S) URL\", 3);\n\t\t\tconst timeout = AbortSignal.timeout(6e4);\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tredirect: \"manual\",\n\t\t\t\tsignal: signal ? AbortSignal.any([signal, timeout]) : timeout\n\t\t\t});\n\t\t\tif (response.status >= 300 && response.status < 400) {\n\t\t\t\tconst location = response.headers.get(\"location\");\n\t\t\t\tawait response.body?.cancel();\n\t\t\t\tif (!location) throw new ImgRelayError(\"image_download_error\", \"图片重定向缺少目标地址\", 3);\n\t\t\t\tcurrent = new URL(location, url).toString();\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!response.ok) {\n\t\t\t\tawait response.body?.cancel();\n\t\t\t\tthrow new ImgRelayError(\"image_download_error\", `图片下载返回 HTTP ${response.status}`, 3, response.status);\n\t\t\t}\n\t\t\treturn await readBounded(response, MAX_IMAGE_BYTES);\n\t\t}\n\t\tthrow new ImgRelayError(\"image_download_error\", \"图片下载重定向超过三次\", 3);\n\t} catch (error) {\n\t\tif (signal?.aborted) throw new ImgRelayError(\"interrupted\", \"已停止本地保存;无法保证取消已提交的上游生成\", 130);\n\t\tif (error instanceof ImgRelayError) throw error;\n\t\tthrow new ImgRelayError(\"image_download_error\", \"图片下载超时或网络失败;不会重新生成图片\", 3);\n\t}\n}\nfunction usageNumbers(value, depth = 0) {\n\tif (depth > 4) return void 0;\n\tif (typeof value === \"number\" && Number.isFinite(value)) return value;\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return void 0;\n\tconst entries = Object.entries(value).slice(0, 100).flatMap(([key, item]) => {\n\t\tif (!/^[a-z_][a-z0-9_]{0,63}$/i.test(key)) return [];\n\t\tconst result = usageNumbers(item, depth + 1);\n\t\treturn result === void 0 ? [] : [[key, result]];\n\t});\n\treturn entries.length ? Object.fromEntries(entries) : void 0;\n}\nasync function generate(store, options) {\n\tconst prepared = await prepareRequest(store, options);\n\tconst { outputDir, requestedModel: model } = prepared.details;\n\tconst key = await store.key(prepared.provider);\n\tconst requestId = randomUUID();\n\tconst recordPath = join(outputDir, `${requestId}-report.json`);\n\tconst data = {\n\t\t...prepared.details,\n\t\trequestId,\n\t\trequestedCount: prepared.details.parameters.n || 1,\n\t\treturnedCount: 0,\n\t\timages: [],\n\t\tfailures: [],\n\t\trecordPath,\n\t\tsubmissionStatus: \"not_submitted\"\n\t};\n\tconst record = {\n\t\tschemaVersion: 1,\n\t\tcreatedAt: (/* @__PURE__ */ new Date()).toISOString(),\n\t\tprompt: options.prompt,\n\t\t...data\n\t};\n\ttry {\n\t\tawait mkdir(outputDir, { recursive: true });\n\t\tif (options.filename && !options.overwrite) try {\n\t\t\tawait access(join(outputDir, options.filename));\n\t\t\tthrow new ImgRelayError(\"save_error\", \"目标文件已存在,请使用其他文件名或显式 --overwrite\", 4);\n\t\t} catch (error) {\n\t\t\tif (!isNotFound(error)) throw error;\n\t\t}\n\t\tawait writeFile(recordPath, `${JSON.stringify(store.redactor.value({\n\t\t\t...record,\n\t\t\tstatus: \"prepared\"\n\t\t}), null, 2)}\\n`, {\n\t\t\tflag: \"wx\",\n\t\t\tmode: 384\n\t\t});\n\t} catch (error) {\n\t\tif (error instanceof ImgRelayError) throw error;\n\t\tthrow new ImgRelayError(\"save_error\", \"无法创建输出目录或请求记录;未提交生成请求\", 4);\n\t}\n\tlet outcome;\n\ttry {\n\t\tvalidateRequest(prepared);\n\t\tdata.parameters = prepared.details.parameters;\n\t\tconst body = {\n\t\t\tmodel,\n\t\t\tprompt: options.prompt\n\t\t};\n\t\tfor (const [name, value] of Object.entries(data.parameters)) {\n\t\t\tconst wire = {\n\t\t\t\toutputFormat: \"output_format\",\n\t\t\t\tresponseFormat: \"response_format\"\n\t\t\t}[name] || name;\n\t\t\tbody[wire] = value;\n\t\t}\n\t\tif (options.signal?.aborted) throw new ImgRelayError(\"interrupted\", \"用户中断,未提交生成请求\", 130);\n\t\toptions.progress?.(\"正在等待生图接口,生成请求只提交一次…\");\n\t\tdata.submissionStatus = \"submitted\";\n\t\tconst response = await requestJson({\n\t\t\turl: data.endpoint,\n\t\t\tkey,\n\t\t\tredactor: store.redactor,\n\t\t\tmethod: \"POST\",\n\t\t\tbody,\n\t\t\ttimeoutSeconds: data.timeoutSeconds,\n\t\t\t...options.signal ? { signal: options.signal } : {}\n\t\t});\n\t\tdata.submissionStatus = \"result_received\";\n\t\tif (!response || typeof response !== \"object\" || !(\"data\" in response) || !Array.isArray(response.data) || response.data.length === 0) throw new ImgRelayError(\"invalid_response\", \"上游响应没有有效的 data[] 图片结果\", 3);\n\t\tif (\"model\" in response && typeof response.model === \"string\") data.reportedModel = response.model;\n\t\tif (\"usage\" in response) {\n\t\t\tconst usage = usageNumbers(response.usage);\n\t\t\tif (usage !== void 0) data.usage = usage;\n\t\t}\n\t\tdata.returnedCount = response.data.length;\n\t\tfor (const [offset, item] of response.data.entries()) {\n\t\t\tconst index = offset + 1;\n\t\t\ttry {\n\t\t\t\tif (options.signal?.aborted) throw new ImgRelayError(\"interrupted\", \"用户中断保存,已保存的文件保持不变\", 130);\n\t\t\t\tif (!item || typeof item !== \"object\") throw new ImgRelayError(\"invalid_response\", \"图片条目不是对象\", 3);\n\t\t\t\tlet bytes;\n\t\t\t\tif (\"b64_json\" in item && typeof item.b64_json === \"string\" && item.b64_json) bytes = base64Bytes(item.b64_json);\n\t\t\t\telse if (\"url\" in item && typeof item.url === \"string\" && item.url) bytes = await download(item.url, options.signal);\n\t\t\t\telse throw new ImgRelayError(\"invalid_response\", \"图片条目缺少 b64_json 或 url\", 3);\n\t\t\t\tlet dimensions;\n\t\t\t\tlet format;\n\t\t\t\ttry {\n\t\t\t\t\tformat = await fileTypeFromBuffer(bytes);\n\t\t\t\t\tdimensions = imageSize(bytes);\n\t\t\t\t\tif (!format?.mime.startsWith(\"image/\") || !dimensions.width || !dimensions.height) throw new Error(\"Invalid image\");\n\t\t\t\t} catch {\n\t\t\t\t\tthrow new ImgRelayError(\"image_decode_error\", \"返回数据不是可识别的有效图片\", 3);\n\t\t\t\t}\n\t\t\t\tconst stem = options.filename ? parse(options.filename).name : requestId;\n\t\t\t\tconst sequence = !options.filename || response.data.length > 1 ? `-${String(index).padStart(2, \"0\")}` : \"\";\n\t\t\t\tconst path = join(outputDir, `${stem}${sequence}.${format.ext}`);\n\t\t\t\tconst handle = await open(path, options.overwrite ? \"w\" : \"wx\", 384).catch(() => {\n\t\t\t\t\tthrow new ImgRelayError(\"save_error\", \"无法保存图片;请检查文件重名和目录权限\", 4);\n\t\t\t\t});\n\t\t\t\ttry {\n\t\t\t\t\tawait handle.writeFile(bytes);\n\t\t\t\t\tawait handle.sync();\n\t\t\t\t} catch {\n\t\t\t\t\tawait handle.close().catch(() => {});\n\t\t\t\t\tawait unlink(path).catch(() => {});\n\t\t\t\t\tthrow new ImgRelayError(\"save_error\", \"图片写入失败;不会重新提交生成\", 4);\n\t\t\t\t} finally {\n\t\t\t\t\tawait handle.close().catch(() => {});\n\t\t\t\t}\n\t\t\t\tdata.images.push({\n\t\t\t\t\tindex,\n\t\t\t\t\tpath,\n\t\t\t\t\tformat: format.ext,\n\t\t\t\t\twidth: dimensions.width,\n\t\t\t\t\theight: dimensions.height,\n\t\t\t\t\tbytes: bytes.length\n\t\t\t\t});\n\t\t\t\toptions.progress?.(`已保存 ${index}/${data.returnedCount} 张图片`);\n\t\t\t} catch (error) {\n\t\t\t\tdata.failures.push({\n\t\t\t\t\tindex,\n\t\t\t\t\terror: store.redactor.error(error)\n\t\t\t\t});\n\t\t\t\tif (error instanceof ImgRelayError && error.category === \"interrupted\") throw error;\n\t\t\t}\n\t\t}\n\t\tconst failed = data.failures.length > 0;\n\t\tconst error = data.failures[0]?.error;\n\t\toutcome = data.images.length ? {\n\t\t\tstatus: failed ? \"partial_success\" : \"success\",\n\t\t\texitCode: failed ? 5 : 0,\n\t\t\tdata\n\t\t} : {\n\t\t\tstatus: \"error\",\n\t\t\texitCode: data.failures.some((failure) => failure.error.category === \"save_error\") ? 4 : 3,\n\t\t\tdata,\n\t\t\t...error ? { error } : {}\n\t\t};\n\t} catch (error) {\n\t\tconst info = store.redactor.error(error);\n\t\tif (info.category === \"result_unknown\") data.submissionStatus = \"unknown\";\n\t\toutcome = {\n\t\t\tstatus: info.category === \"result_unknown\" ? \"unknown\" : info.category === \"interrupted\" ? \"interrupted\" : \"error\",\n\t\t\texitCode: error instanceof ImgRelayError ? error.exitCode : 1,\n\t\t\tdata,\n\t\t\terror: info\n\t\t};\n\t}\n\ttry {\n\t\tawait writeAtomic(recordPath, store.redactor.value({\n\t\t\t...record,\n\t\t\t...data,\n\t\t\tstatus: outcome.status,\n\t\t\terror: outcome.error || null,\n\t\t\tcompletedAt: (/* @__PURE__ */ new Date()).toISOString()\n\t\t}));\n\t} catch {\n\t\tdata.recordPath = null;\n\t\treturn {\n\t\t\tstatus: \"error\",\n\t\t\texitCode: 4,\n\t\t\tdata,\n\t\t\terror: {\n\t\t\t\tcategory: \"save_error\",\n\t\t\t\tmessage: \"生成记录保存失败;已保存的图片路径仍可使用,不会重新生成\"\n\t\t\t}\n\t\t};\n\t}\n\treturn outcome;\n}\n\n//#endregion\n//#region src/models.ts\nconst modelsResponse = z.object({ data: z.array(z.object({\n\tid: z.string().min(1),\n\ttype: z.string().optional()\n})) });\nconst cachedModels = z.object({\n\tfetchedAt: z.iso.datetime(),\n\tmodels: modelsResponse.shape.data,\n\turl: z.string(),\n\trevision: z.number()\n});\nasync function discoverModels(provider, key, redactor, signal) {\n\tconst url = resolveEndpoint(provider.baseUrl, provider.endpoints.models || \"/v1/models\");\n\tconst response = modelsResponse.safeParse(await requestJson({\n\t\turl,\n\t\tkey,\n\t\tredactor,\n\t\tretry: true,\n\t\t...signal ? { signal } : {}\n\t}));\n\tif (!response.success) throw new ImgRelayError(\"invalid_response\", \"模型接口未返回 data[].id;仍可手动配置模型后生成\", 3);\n\treturn response.data.data;\n}\nasync function models(store, options = {}) {\n\tconst selected = await store.selected(options.provider);\n\tconst key = await store.key(selected.provider);\n\tconst url = resolveEndpoint(selected.provider.baseUrl, selected.provider.endpoints.models || \"/v1/models\");\n\tconst cacheKey = createHash(\"sha256\").update(JSON.stringify([\n\t\tselected.name,\n\t\turl,\n\t\tselected.provider.revision,\n\t\tkey\n\t])).digest(\"hex\");\n\tif (!options.refresh) {\n\t\tconst cache = z.record(z.string(), z.unknown()).safeParse(await store.cache());\n\t\tconst cached = cachedModels.safeParse(cache.success ? cache.data[cacheKey] : void 0);\n\t\tif (cached.success && Date.now() - Date.parse(cached.data.fetchedAt) >= 0 && Date.now() - Date.parse(cached.data.fetchedAt) < 9e5) return {\n\t\t\t...cached.data,\n\t\t\tprovider: selected.name,\n\t\t\tcached: true\n\t\t};\n\t}\n\tconst discovered = await discoverModels(selected.provider, key, store.redactor, options.signal);\n\tconst result = {\n\t\tfetchedAt: (/* @__PURE__ */ new Date()).toISOString(),\n\t\tmodels: discovered,\n\t\turl,\n\t\trevision: selected.provider.revision\n\t};\n\tawait store.saveCache(cacheKey, result);\n\treturn {\n\t\t...result,\n\t\tprovider: selected.name,\n\t\tcached: false\n\t};\n}\nasync function doctor(store, options = {}) {\n\tlet selected;\n\ttry {\n\t\tselected = await store.selected(options.provider);\n\t} catch (error) {\n\t\tconst info = store.redactor.error(error);\n\t\treturn {\n\t\t\texitCode: error instanceof ImgRelayError ? error.exitCode : 1,\n\t\t\terror: info,\n\t\t\tdata: {\n\t\t\t\tprovider: options.provider || null,\n\t\t\t\tendpoints: null,\n\t\t\t\tconfiguration: \"invalid\",\n\t\t\t\tauthentication: \"not_checked\",\n\t\t\t\tmodelDiscovery: { status: \"not_checked\" },\n\t\t\t\tgeneration: \"not_verified\"\n\t\t\t}\n\t\t};\n\t}\n\tconst endpoints = {\n\t\tgenerate: resolveEndpoint(selected.provider.baseUrl, selected.provider.endpoints.generate || \"/v1/images/generations\"),\n\t\tmodels: resolveEndpoint(selected.provider.baseUrl, selected.provider.endpoints.models || \"/v1/models\")\n\t};\n\ttry {\n\t\tconst result = await models(store, {\n\t\t\t...options,\n\t\t\trefresh: true\n\t\t});\n\t\treturn {\n\t\t\texitCode: 0,\n\t\t\tdata: {\n\t\t\t\tprovider: selected.name,\n\t\t\t\tendpoints,\n\t\t\t\tconfiguration: \"valid\",\n\t\t\t\tauthentication: \"verified_for_models\",\n\t\t\t\tmodelDiscovery: result,\n\t\t\t\tgeneration: \"not_verified\",\n\t\t\t\tdefaultModelListed: selected.provider.defaultModel ? result.models.some((model) => model.id === selected.provider.defaultModel) : null\n\t\t\t}\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof ImgRelayError && error.category === \"interrupted\") throw error;\n\t\tconst info = store.redactor.error(error);\n\t\treturn {\n\t\t\texitCode: error instanceof ImgRelayError ? error.exitCode : 1,\n\t\t\terror: info,\n\t\t\tdata: {\n\t\t\t\tprovider: selected.name,\n\t\t\t\tendpoints,\n\t\t\t\tconfiguration: \"valid\",\n\t\t\t\tauthentication: info.category === \"auth_error\" ? \"failed\" : \"unknown\",\n\t\t\t\tmodelDiscovery: {\n\t\t\t\t\tstatus: \"unavailable\",\n\t\t\t\t\terror: info\n\t\t\t\t},\n\t\t\t\tgeneration: \"not_verified\",\n\t\t\t\tmessage: \"模型列表不可用时,仍可手动设置模型;生成能力尚未验证\"\n\t\t\t}\n\t\t};\n\t}\n}\n\n//#endregion\n//#region src/store.ts\nfunction defaultConfigDirectory() {\n\tif (process.env.IMGRELAY_CONFIG_DIR) return resolve(process.env.IMGRELAY_CONFIG_DIR);\n\treturn join(homedir(), \".imgrelay\");\n}\nvar Store = class {\n\tdirectory;\n\tredactor = new Redactor();\n\tinitialized = false;\n\tconstructor(directory = defaultConfigDirectory()) {\n\t\tthis.directory = resolve(directory);\n\t\tif (this.directory === parse(this.directory).root) throw new ImgRelayError(\"config_error\", \"配置目录不能是文件系统根目录\");\n\t}\n\tasync config() {\n\t\ttry {\n\t\t\tconst raw = await readJson(join(this.directory, \"config.json\"));\n\t\t\tif (raw && typeof raw === \"object\" && \"schemaVersion\" in raw && raw.schemaVersion !== 1) throw new ImgRelayError(\"config_error\", \"不支持此配置版本;当前仅支持 schemaVersion=1\");\n\t\t\tconst result = configSchema.safeParse(raw);\n\t\t\tif (!result.success) throw new ImgRelayError(\"config_error\", \"配置文件结构或版本无效;请检查 config.json\");\n\t\t\tfor (const provider of Object.values(result.data.providers)) if (provider.apiKey) this.redactor.add(provider.apiKey);\n\t\t\treturn result.data;\n\t\t} catch (error) {\n\t\t\tif (isNotFound(error)) return {\n\t\t\t\tschemaVersion: 1,\n\t\t\t\tproviders: {}\n\t\t\t};\n\t\t\tif (error instanceof ImgRelayError) throw error;\n\t\t\tthrow new ImgRelayError(\"config_error\", \"无法读取配置文件;请检查文件格式及访问权限\");\n\t\t}\n\t}\n\tasync selected(name) {\n\t\tconst config = await this.config();\n\t\tconst selected = name || config.defaultProvider;\n\t\tif (!selected) throw new ImgRelayError(\"config_error\", \"未设置默认供应商,请运行 imgrelay provider use <名称>\");\n\t\tconst provider = Object.hasOwn(config.providers, selected) ? config.providers[selected] : void 0;\n\t\tif (!provider) throw new ImgRelayError(\"config_error\", `供应商 ${selected} 不存在,请运行 imgrelay provider add ${selected}`);\n\t\treturn {\n\t\t\tname: selected,\n\t\t\tprovider\n\t\t};\n\t}\n\tasync initialize() {\n\t\tif (!this.initialized) {\n\t\t\tawait mkdir(this.directory, { recursive: true });\n\t\t\tthis.initialized = true;\n\t\t}\n\t}\n\tasync locked(operation) {\n\t\tawait this.initialize();\n\t\tconst lock = join(this.directory, \".write-lock\");\n\t\tconst owner = join(lock, \"owner.json\");\n\t\tconst deadline = Date.now() + 1e4;\n\t\tfor (;;) try {\n\t\t\tawait mkdir(lock);\n\t\t\tbreak;\n\t\t} catch (error) {\n\t\t\tif (!(error instanceof Error && \"code\" in error && error.code === \"EEXIST\")) throw error;\n\t\t\ttry {\n\t\t\t\tconst data = z.object({ pid: z.number().int().positive() }).parse(await readJson(owner));\n\t\t\t\ttry {\n\t\t\t\t\tprocess.kill(data.pid, 0);\n\t\t\t\t} catch (checkError) {\n\t\t\t\t\tif (checkError instanceof Error && \"code\" in checkError && checkError.code === \"ESRCH\") {\n\t\t\t\t\t\tawait unlink(owner);\n\t\t\t\t\t\tawait rmdir(lock);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\ttry {\n\t\t\t\t\tif (Date.now() - (await lstat(lock)).mtimeMs > 6e4) {\n\t\t\t\t\t\tawait unlink(owner).catch(() => {});\n\t\t\t\t\t\tawait rmdir(lock);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t} catch {}\n\t\t\t}\n\t\t\tif (Date.now() >= deadline) throw new ImgRelayError(\"config_busy\", \"配置正在被其他进程修改,请稍后重试\");\n\t\t\tawait setTimeout(50);\n\t\t}\n\t\ttry {\n\t\t\tawait writeFile(owner, JSON.stringify({ pid: process.pid }));\n\t\t\treturn await operation();\n\t\t} finally {\n\t\t\tawait unlink(owner).catch(() => {});\n\t\t\tawait rmdir(lock).catch(() => {});\n\t\t}\n\t}\n\tasync key(provider) {\n\t\tconst key = provider.apiKey;\n\t\tif (!key) throw new ImgRelayError(\"credential_error\", \"未配置 API 密钥,请运行 imgrelay provider edit <名称>\");\n\t\tif (/[\\r\\n\\0]/.test(key)) throw new ImgRelayError(\"credential_error\", \"密钥不能包含换行或空字符\");\n\t\tthis.redactor.add(key);\n\t\treturn key;\n\t}\n\tasync put(name, input, options = {}) {\n\t\tif (!providerNameSchema.safeParse(name).success) throw new ImgRelayError(\"input_error\", \"供应商名称只能包含字母、数字、下划线和连字符\");\n\t\tif (input.apiKey) this.redactor.add(input.apiKey);\n\t\tif (options.secret) this.redactor.add(options.secret);\n\t\tconst proposed = parseProvider({\n\t\t\t...input,\n\t\t\t...options.secret !== void 0 ? { apiKey: options.secret } : {}\n\t\t});\n\t\tif (proposed.apiKey) this.redactor.add(proposed.apiKey);\n\t\treturn this.locked(async () => {\n\t\t\tconst config = await this.config();\n\t\t\tconst previous = Object.hasOwn(config.providers, name) ? config.providers[name] : void 0;\n\t\t\tif (options.edit ? !previous : previous) throw new ImgRelayError(\"config_error\", options.edit ? \"供应商不存在\" : \"供应商已存在,请使用 provider edit\");\n\t\t\tif (options.expectedRevision !== void 0 && previous?.revision !== options.expectedRevision) throw new ImgRelayError(\"config_busy\", \"配置已被其他进程修改,请重新执行编辑\");\n\t\t\tproposed.revision = (previous?.revision || 0) + 1;\n\t\t\tconfig.providers[name] = proposed;\n\t\t\tif (options.makeDefault) config.defaultProvider = name;\n\t\t\tawait writeAtomic(join(this.directory, \"config.json\"), config);\n\t\t\treturn proposed;\n\t\t});\n\t}\n\tasync use(name) {\n\t\tawait this.locked(async () => {\n\t\t\tconst config = await this.config();\n\t\t\tif (!Object.hasOwn(config.providers, name)) throw new ImgRelayError(\"config_error\", \"供应商不存在\");\n\t\t\tconfig.defaultProvider = name;\n\t\t\tawait writeAtomic(join(this.directory, \"config.json\"), config);\n\t\t});\n\t}\n\tasync remove(name) {\n\t\tawait this.locked(async () => {\n\t\t\tconst config = await this.config();\n\t\t\tif (!Object.hasOwn(config.providers, name)) throw new ImgRelayError(\"config_error\", \"供应商不存在\");\n\t\t\tdelete config.providers[name];\n\t\t\tif (config.defaultProvider === name) delete config.defaultProvider;\n\t\t\tawait writeAtomic(join(this.directory, \"config.json\"), config);\n\t\t});\n\t}\n\tasync cache() {\n\t\ttry {\n\t\t\treturn await readJson(join(this.directory, \"models-cache.json\"));\n\t\t} catch {\n\t\t\treturn {};\n\t\t}\n\t}\n\tasync saveCache(key, value) {\n\t\tawait this.locked(async () => {\n\t\t\tconst parsed = z.record(z.string(), z.unknown()).safeParse(await this.cache());\n\t\t\tconst cache = parsed.success ? parsed.data : {};\n\t\t\tcache[key] = value;\n\t\t\tconst entries = Object.entries(cache).slice(-100);\n\t\t\tawait writeAtomic(join(this.directory, \"models-cache.json\"), Object.fromEntries(entries));\n\t\t});\n\t}\n};\n\n//#endregion\nexport { CUBENCE_PRESET, ImgRelayError, KNOWN_MODEL_CAPABILITIES, Redactor, Store, configSchema, defaultConfigDirectory, discoverModels, doctor, generate, modelCapabilitySchema, models, normalizeBaseUrl, parseProvider, previewGenerate, providerNameSchema, providerSchema, resolveEndpoint };\n//# sourceMappingURL=index.mjs.map","","import { readFile } from 'node:fs/promises'\nimport { resolve } from 'node:path'\nimport type { Readable } from 'node:stream'\n\nimport { ImgRelayError } from '@imgrelay/core'\nimport type { PromptSource } from '@imgrelay/core'\n\nexport interface PromptFlags {\n promptFile?: string\n promptStdin?: boolean\n}\n\nfunction interrupted(): ImgRelayError {\n return new ImgRelayError('interrupted', '用户中断读取提示词,未提交生成请求', 130)\n}\n\nexport async function readPrompt(\n flags: PromptFlags,\n signal?: AbortSignal,\n stdin: Readable & { isTTY?: boolean } = process.stdin,\n): Promise<{ prompt: string; promptSource: PromptSource }> {\n if (Number(flags.promptFile !== undefined) + Number(Boolean(flags.promptStdin)) !== 1)\n throw new ImgRelayError('input_error', '必须且只能指定 --prompt-file 或 --prompt-stdin')\n if (signal?.aborted) throw interrupted()\n let bytes: Buffer\n let promptSource: PromptSource\n if (flags.promptFile !== undefined) {\n if (!flags.promptFile.trim())\n throw new ImgRelayError('input_error', '--prompt-file 路径不能为空')\n const path = resolve(flags.promptFile)\n try {\n bytes = await readFile(path, signal ? { signal } : {})\n } catch {\n if (signal?.aborted) throw interrupted()\n throw new ImgRelayError('input_error', '无法读取 --prompt-file;请检查文件路径及访问权限')\n }\n promptSource = { type: 'file', path }\n } else {\n if (stdin.isTTY)\n throw new ImgRelayError(\n 'input_error',\n '--prompt-stdin 需要管道或重定向输入;也可使用 --prompt-file',\n )\n const abort = () => stdin.destroy(interrupted())\n signal?.addEventListener('abort', abort, { once: true })\n const chunks: Buffer[] = []\n try {\n for await (const chunk of stdin) chunks.push(Buffer.from(chunk))\n bytes = Buffer.concat(chunks)\n } catch {\n if (signal?.aborted) throw interrupted()\n throw new ImgRelayError('input_error', '无法读取 stdin 提示词')\n } finally {\n signal?.removeEventListener('abort', abort)\n }\n promptSource = { type: 'stdin' }\n }\n if (signal?.aborted) throw interrupted()\n let prompt: string\n try {\n prompt = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(bytes)\n } catch {\n throw new ImgRelayError('input_error', '提示词必须是有效 UTF-8 文本')\n }\n if (prompt.startsWith('\\uFEFF')) prompt = prompt.slice(1)\n if (!prompt.trim()) throw new ImgRelayError('input_error', '提示词不能为空或全空白')\n return { prompt, promptSource }\n}\n","/* Interactive prompts must be shown one at a time. */\n/* eslint-disable no-await-in-loop */\nimport { readFile } from 'node:fs/promises'\nimport { resolve } from 'node:path'\n\nimport * as prompts from '@clack/prompts'\nimport { CUBENCE_PRESET, discoverModels, ImgRelayError, parseProvider } from '@imgrelay/core'\nimport type { Provider, ProviderInput, Store } from '@imgrelay/core'\nimport type { Command } from 'commander'\n\nexport interface ProviderFlags {\n baseUrl?: string\n protocol?: string\n preset?: string\n model?: string\n clearKey?: boolean\n size?: string\n n?: string\n quality?: string\n outputFormat?: string\n responseFormat?: string\n generationPath?: string\n modelsPath?: string\n capabilitiesFile?: string\n timeout?: string\n default?: boolean\n}\n\nfunction answer(value: string | symbol): string\nfunction answer(value: boolean | symbol): boolean\nfunction answer(value: string | boolean | symbol): string | boolean {\n if (typeof value === 'symbol')\n throw new ImgRelayError('interrupted', '用户取消配置,未保存修改', 130)\n return value\n}\n\nexport function providerOptions(command: Command): Command {\n return command\n .option('--base-url <URL>', 'API 基础地址,推荐包含 /v1')\n .option('--protocol <协议>', '首版支持 openai-images')\n .option('--preset <名称>', '使用已验证配置预设:cubence')\n .option('--model <ID>', '默认模型,允许手动填写')\n .option('--clear-key', '清除配置中保存的密钥')\n .option('--default', '保存后设为默认供应商')\n .option('--size <尺寸>', '默认尺寸')\n .option('--n <数量>', '默认生成数量')\n .option('--quality <质量>', '默认质量')\n .option('--output-format <格式>', '默认图片格式')\n .option('--response-format <格式>', '供应商要求的返回格式:url 或 b64_json')\n .option('--generation-path <路径>', '生成端点覆盖')\n .option('--models-path <路径>', '模型端点覆盖')\n .option('--capabilities-file <文件>', '按模型的能力覆盖 JSON 文件')\n .option('--timeout <秒数>', '默认生成超时')\n}\n\nexport async function configureProvider(\n store: Store,\n name: string,\n flags: ProviderFlags,\n interactive: boolean,\n signal: AbortSignal,\n existing?: Provider,\n): Promise<Provider> {\n if (flags.preset && flags.preset !== 'cubence')\n throw new ImgRelayError('input_error', '未知预设;当前提供 cubence')\n if (!existing && !interactive)\n throw new ImgRelayError(\n 'config_error',\n '新增供应商需要隐藏输入 API 密钥,请在交互终端不带 --json 运行 provider add',\n )\n const input: ProviderInput = {\n protocol: 'openai-images',\n baseUrl: '',\n ...(flags.preset ? CUBENCE_PRESET : {}),\n ...existing,\n }\n if (flags.protocol) {\n if (flags.protocol !== 'openai-images')\n throw new ImgRelayError('config_error', '首版仅支持 openai-images 协议')\n input.protocol = flags.protocol\n }\n if (flags.baseUrl !== undefined) input.baseUrl = flags.baseUrl\n if (flags.model !== undefined) input.defaultModel = flags.model\n input.defaults = { ...input.defaults }\n input.endpoints = { ...input.endpoints }\n if (flags.size !== undefined) input.defaults.size = flags.size\n if (flags.n !== undefined) input.defaults.n = Number(flags.n)\n if (flags.quality !== undefined) input.defaults.quality = flags.quality\n if (flags.outputFormat !== undefined) input.defaults.outputFormat = flags.outputFormat\n if (flags.responseFormat !== undefined) {\n if (flags.responseFormat !== 'url' && flags.responseFormat !== 'b64_json')\n throw new ImgRelayError('input_error', '返回格式只能是 url 或 b64_json')\n input.defaults.responseFormat = flags.responseFormat\n }\n if (flags.generationPath !== undefined) input.endpoints.generate = flags.generationPath\n if (flags.modelsPath !== undefined) input.endpoints.models = flags.modelsPath\n if (flags.timeout !== undefined) input.timeoutSeconds = Number(flags.timeout)\n if (flags.capabilitiesFile) {\n try {\n const modelOverrides: unknown = JSON.parse(\n await readFile(resolve(flags.capabilitiesFile), 'utf8'),\n )\n input.modelOverrides = parseProvider({ ...input, modelOverrides }).modelOverrides\n } catch {\n throw new ImgRelayError('input_error', '能力覆盖文件必须是可读的 UTF-8 JSON')\n }\n }\n let secret: string | undefined\n if (flags.clearKey) delete input.apiKey\n if (interactive) {\n prompts.intro(existing ? `编辑供应商 ${name}` : `添加供应商 ${name}`)\n if (flags.baseUrl === undefined)\n input.baseUrl = answer(\n await prompts.text({\n message: 'API 基础地址',\n initialValue: input.baseUrl,\n validate: (value) => (value?.trim() ? undefined : '请输入地址'),\n }),\n )\n if (!flags.clearKey) {\n secret =\n answer(\n await prompts.password({\n message: input.apiKey ? 'API 密钥(留空保留当前密钥)' : 'API 密钥',\n validate: (value) => (value?.trim() || input.apiKey ? undefined : '密钥不能为空'),\n }),\n ).trim() || undefined\n if (secret) store.redactor.add(secret)\n }\n }\n if (!existing && !secret) throw new ImgRelayError('config_error', '新增供应商需要非空 API 密钥')\n if (interactive && flags.model === undefined) {\n let ids: string[] = []\n try {\n const key = secret || (await store.key(input))\n ids = (await discoverModels(parseProvider(input), key, store.redactor, signal)).map(\n (model) => model.id,\n )\n } catch (error) {\n if (error instanceof ImgRelayError && error.category === 'interrupted') throw error\n prompts.log.warn('未能查询模型列表,可以手动填写模型 ID;生成能力尚未验证')\n }\n const choice = ids.length\n ? answer(\n await prompts.select({\n message: '默认模型',\n options: [\n ...ids.map((id) => ({ value: id, label: store.redactor.text(id) })),\n { value: '\\0manual', label: '手动填写模型 ID' },\n ],\n }),\n )\n : '\\0manual'\n input.defaultModel =\n choice === '\\0manual'\n ? answer(\n await prompts.text({\n message: '默认模型(留空可稍后设置)',\n initialValue: input.defaultModel || '',\n }),\n )\n : choice\n if (!input.defaultModel) delete input.defaultModel\n }\n if (\n interactive &&\n answer(\n await prompts.confirm({\n message: '设置尺寸、数量、质量和格式的默认值?',\n initialValue: false,\n }),\n )\n ) {\n for (const [field, label] of [\n ['size', '尺寸'],\n ['n', '数量'],\n ['quality', '质量'],\n ['outputFormat', '图片格式'],\n ] as const) {\n const value = answer(\n await prompts.text({\n message: `${label}(留空表示不设置)`,\n initialValue: String(input.defaults[field] || ''),\n }),\n )\n if (value) Object.assign(input.defaults, { [field]: field === 'n' ? Number(value) : value })\n else delete input.defaults[field]\n }\n }\n const makeDefault =\n flags.default ||\n (interactive\n ? answer(\n await prompts.confirm({\n message: '设为默认供应商?',\n initialValue: !(await store.config()).defaultProvider,\n }),\n )\n : false)\n const saved = await store.put(name, input, {\n ...(existing ? { edit: true, expectedRevision: existing.revision } : {}),\n ...(secret ? { secret } : {}),\n makeDefault,\n })\n if (interactive) prompts.outro('配置已保存;此流程没有生成图片')\n return saved\n}\n","#!/usr/bin/env node\nimport { doctor, generate, ImgRelayError, models, previewGenerate, Store } from '@imgrelay/core'\nimport type { ErrorInfo } from '@imgrelay/core'\nimport { Command, CommanderError } from 'commander'\n\nimport packageJson from '../package.json' with { type: 'json' }\nimport { readPrompt } from './prompt.js'\nimport { configureProvider, providerOptions } from './provider.js'\nimport type { ProviderFlags } from './provider.js'\n\nconst json = process.argv.includes('--json')\nconst controller = new AbortController()\nprocess.once('SIGINT', () => controller.abort())\nprocess.once('SIGTERM', () => controller.abort())\nlet commandName = 'imgrelay'\nlet outputWritten = false\nlet helpOutput = ''\nlet store: Store | undefined\n\nfunction output(\n data: unknown,\n options: { status?: string; exitCode?: number; error?: ErrorInfo } = {},\n): void {\n if (outputWritten) return\n outputWritten = true\n const envelope = {\n schemaVersion: 1,\n command: commandName,\n status: options.status || 'success',\n data,\n error: options.error || null,\n }\n const safe = store ? store.redactor.value(envelope) : envelope\n if (json) process.stdout.write(`${JSON.stringify(safe)}\\n`)\n else {\n if (options.error)\n process.stderr.write(\n `${store?.redactor.text(options.error.message) || options.error.message}\\n`,\n )\n if (data !== null)\n process.stdout.write(\n `${JSON.stringify(store ? store.redactor.value(data) : data, null, 2)}\\n`,\n )\n }\n process.exitCode = options.exitCode || 0\n}\n\nfunction active(name: string): Store {\n commandName = name\n store ||= new Store()\n return store\n}\n\nconst program = new Command()\n .name('imgrelay')\n .description('通过统一入口调用 OpenAI Images 兼容中转站')\n .version(packageJson.version)\n .option('--json', '输出一个最终 JSON 对象,禁用交互输入')\n .exitOverride()\n .configureOutput({\n writeOut: (value) => {\n if (json) helpOutput += value\n else process.stdout.write(value)\n },\n writeErr: (value) => {\n if (!json) process.stderr.write(value)\n },\n })\n\nconst provider = program.command('provider').description('管理供应商配置与凭据')\nproviderOptions(provider.command('add <名称>').description('添加供应商')).action(\n async (name: string, flags: ProviderFlags) => {\n const current = active('provider add')\n const result = await configureProvider(\n current,\n name,\n flags,\n !json && process.stdin.isTTY && process.stdout.isTTY,\n controller.signal,\n )\n output({ provider: name, configuration: result })\n },\n)\nproviderOptions(provider.command('edit <名称>').description('修改供应商')).action(\n async (name: string, flags: ProviderFlags) => {\n const current = active('provider edit')\n const existing = await current.selected(name)\n const result = await configureProvider(\n current,\n name,\n flags,\n !json && process.stdin.isTTY && process.stdout.isTTY,\n controller.signal,\n existing.provider,\n )\n output({ provider: name, configuration: result })\n },\n)\nprovider\n .command('list')\n .description('列出供应商摘要')\n .action(async () => {\n const current = active('provider list')\n const config = await current.config()\n output({\n defaultProvider: config.defaultProvider || null,\n providers: Object.entries(config.providers).map(([name, entry]) => ({\n name,\n protocol: entry.protocol,\n baseUrl: entry.baseUrl,\n defaultModel: entry.defaultModel || null,\n credentialSource: entry.apiKey ? 'config' : null,\n default: name === config.defaultProvider,\n })),\n })\n })\nprovider\n .command('show <名称>')\n .description('查看脱敏配置')\n .action(async (name: string) => {\n const current = active('provider show')\n const selected = await current.selected(name)\n output({ provider: name, configuration: selected.provider })\n })\nprovider\n .command('use <名称>')\n .description('设置默认供应商')\n .action(async (name: string) => {\n const current = active('provider use')\n await current.use(name)\n output({ defaultProvider: name })\n })\nprovider\n .command('remove <名称>')\n .description('移除供应商及其已保存的密钥')\n .action(async (name: string) => {\n const current = active('provider remove')\n await current.remove(name)\n output({ removed: name })\n })\nprogram\n .command('models')\n .description('查询模型列表或查看 15 分钟缓存')\n .option('--provider <名称>', '本次使用的供应商')\n .option('--refresh', '强制刷新模型列表')\n .action(async (flags: { provider?: string; refresh?: boolean }) => {\n const current = active('models')\n output(await models(current, { ...flags, signal: controller.signal }))\n })\nprogram\n .command('doctor')\n .description('检查配置与模型接口,不生成图片')\n .option('--provider <名称>', '检查指定供应商')\n .action(async (flags: { provider?: string }) => {\n const current = active('doctor')\n const result = await doctor(current, { ...flags, signal: controller.signal })\n output(result.data, {\n status: result.exitCode ? 'error' : 'success',\n exitCode: result.exitCode,\n ...(result.error ? { error: result.error } : {}),\n })\n })\nprogram\n .command('generate')\n .description('生成图片并保存原图和记录')\n .allowExcessArguments(false)\n .option('--prompt-file <路径>', '读取 UTF-8 提示词文件,与 --prompt-stdin 互斥')\n .option('--prompt-stdin', '从管道或重定向读取 UTF-8 提示词,与 --prompt-file 互斥')\n .option('--dry-run', '离线预览有效请求,不联网、不写文件,无需密钥')\n .option('--provider <名称>', '本次使用的供应商')\n .option('--model <ID>', '本次使用的模型')\n .option('--size <尺寸>', '图片尺寸,如 auto 或 1024x1024')\n .option('--n <数量>', '请求图片数量,不自动拆单')\n .option('--quality <质量>', '请求质量')\n .option('--output-format <格式>', '请求图片格式')\n .option('--output-dir <目录>', '保存目录,默认 output/imagegen')\n .option('--filename <名称>', '文件名;多图追加序号,扩展名按实际格式')\n .option('--overwrite', '允许覆盖图片文件')\n .option('--timeout <秒数>', '生成等待超时,默认 600 秒')\n .action(\n async (flags: {\n promptFile?: string\n promptStdin?: boolean\n dryRun?: boolean\n provider?: string\n model?: string\n size?: string\n n?: string\n quality?: string\n outputFormat?: string\n outputDir?: string\n filename?: string\n overwrite?: boolean\n timeout?: string\n }) => {\n const current = active('generate')\n const prompt = await readPrompt(flags, controller.signal)\n const options = {\n ...prompt,\n ...(flags.provider !== undefined ? { provider: flags.provider } : {}),\n ...(flags.model !== undefined ? { model: flags.model } : {}),\n ...(flags.size !== undefined ? { size: flags.size } : {}),\n ...(flags.n !== undefined ? { n: Number(flags.n) } : {}),\n ...(flags.quality !== undefined ? { quality: flags.quality } : {}),\n ...(flags.outputFormat !== undefined ? { outputFormat: flags.outputFormat } : {}),\n ...(flags.outputDir !== undefined ? { outputDir: flags.outputDir } : {}),\n ...(flags.filename !== undefined ? { filename: flags.filename } : {}),\n ...(flags.timeout !== undefined ? { timeoutSeconds: Number(flags.timeout) } : {}),\n overwrite: Boolean(flags.overwrite),\n signal: controller.signal,\n progress: (message: string) => process.stderr.write(`${message}\\n`),\n }\n if (flags.dryRun) {\n output(await previewGenerate(current, options))\n return\n }\n const result = await generate(current, options)\n output(result.data, {\n status: result.status,\n exitCode: result.exitCode,\n ...(result.error ? { error: result.error } : {}),\n })\n },\n )\nprogram.action(() => {\n if (json) output({ help: program.helpInformation() })\n else program.outputHelp()\n})\n\ntry {\n await program.parseAsync(process.argv)\n} catch (error) {\n if (error instanceof CommanderError && error.exitCode === 0) {\n if (json) output({ help: helpOutput.trim() })\n process.exitCode = 0\n } else {\n const removedPrompt =\n error instanceof CommanderError &&\n error.code === 'commander.unknownOption' &&\n (error.message.includes(\"'--prompt'\") || error.message.includes(\"'--prompt=\"))\n if (removedPrompt) commandName = 'generate'\n const failure =\n error instanceof CommanderError\n ? new ImgRelayError(\n 'input_error',\n removedPrompt\n ? '--prompt 已移除,请改用 --prompt-file <路径> 或 --prompt-stdin'\n : error.message,\n )\n : error\n const info: ErrorInfo = store\n ? store.redactor.error(failure)\n : {\n category: failure instanceof ImgRelayError ? failure.category : 'internal_error',\n message: failure instanceof Error ? failure.message : '发生未知错误',\n }\n output(null, {\n status: info.category === 'interrupted' ? 'interrupted' : 'error',\n exitCode: failure instanceof ImgRelayError ? failure.exitCode : 1,\n error: info,\n })\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "imgrelay",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "通过统一 CLI 调用多家 OpenAI Images 兼容中转站",
5
5
  "homepage": "https://github.com/bingwu-devkit/imgrelay#readme",
6
6
  "bugs": "https://github.com/bingwu-devkit/imgrelay/issues",