wx_ai_proxy_client 0.0.0-stage → 0.1.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
@@ -1,3 +1,410 @@
1
- # Temporary Holding Version
1
+ # wx_ai_proxy_client(Node.js SDK)
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ AI API Proxy 服务的 Node.js 客户端,封装 `chat` / `images` / `videos` / `nano_banana` 等 HTTP 接口。
4
+
5
+ - 零运行时依赖,基于 Node.js 18+ 内置的 `fetch`,服务端和命令行工具都能用。
6
+ - 同时提供 ESM(`import`)与 CommonJS(`require`)两种产物,并自带 TypeScript 类型。
7
+ - 服务端返回的错误统一转换成 `APIRequestError`,携带 HTTP 状态码和服务端的 `detail`。
8
+ - 方法、字段与 Python SDK(`pip install wx_ai_proxy_client`)一一对应。请求、响应字段沿用服务端的 snake_case 命名。
9
+
10
+ ## 安装
11
+
12
+ ```bash
13
+ npm install wx_ai_proxy_client
14
+ ```
15
+
16
+ 要求 Node.js >= 18。更低版本可以通过 `fetch` 选项传入 `node-fetch` 等实现。
17
+
18
+ ## 快速上手
19
+
20
+ ```js
21
+ // ESM
22
+ import { AIProxyClient, APIRequestError } from "wx_ai_proxy_client";
23
+ // CommonJS:const { AIProxyClient, APIRequestError } = require("wx_ai_proxy_client");
24
+
25
+ const client = new AIProxyClient({
26
+ baseUrl: "https://ai-api-proxy.segapi.com", // 默认值,可省略
27
+ apiKey: process.env.AI_PROXY_API_KEY,
28
+ });
29
+
30
+ // 对话(文本 / 多模态)
31
+ const chat = await client.chatGenerate({
32
+ prompt: "用一句话介绍一下这张图",
33
+ image_inputs: [{ image_url: "https://example.com/demo.jpg" }],
34
+ generation_config: { temperature: 0.3 },
35
+ });
36
+ console.log(chat.text);
37
+
38
+ // 生成图片
39
+ const img = await client.generateImage({
40
+ prompt: "a cat reading a book",
41
+ provider: "google",
42
+ model_name: "nano-banana-pro",
43
+ aspect_ratio: "16:9",
44
+ response_type: "url",
45
+ });
46
+ console.log(img.images?.[0]?.image_url);
47
+
48
+ // 生成提示词(结果通常在 text 字段)
49
+ const written = await client.nbWritePrompt({ prompt: "把这句话改写成英文出图提示词:一只戴墨镜的柴犬在海边冲浪" });
50
+ console.log(written.text);
51
+
52
+ // 创建视频任务(异步),然后轮询结果
53
+ const task = await client.generateVideo({
54
+ prompt: "a cat jumping on a tree",
55
+ provider: "falai",
56
+ model_name: "seedance-2",
57
+ duration: 5,
58
+ resolution: "1280x720",
59
+ });
60
+ let result;
61
+ do {
62
+ await new Promise((r) => setTimeout(r, 10_000));
63
+ // provider 要与创建任务时返回的 provider 一致
64
+ result = await client.queryVideoResult({ video_id: task.video_id, provider: task.provider });
65
+ } while (result.status === "queued" || result.status === "processing");
66
+ console.log(result.status, result.video?.video_url ?? result.err_msg);
67
+ ```
68
+
69
+ TypeScript 可以直接使用导出的类型:
70
+
71
+ ```ts
72
+ import { AIProxyClient, type ImageGenerateRequest, type ImageGenerateResponse } from "wx_ai_proxy_client";
73
+ ```
74
+
75
+ ## 客户端选项
76
+
77
+ `new AIProxyClient(options)`:
78
+
79
+ | 选项 | 类型 | 默认值 | 说明 |
80
+ | --- | --- | --- | --- |
81
+ | `baseUrl` | `string` | `https://ai-api-proxy.segapi.com` | 服务地址,可以带路径前缀。 |
82
+ | `apiKey` | `string` | 无 | 以 `Authorization: Bearer <apiKey>` 发送。保存在私有字段里,`console.log(client)` 不会打印出来。 |
83
+ | `timeout` | `number` | `180000` | 超时(毫秒),`0` 表示不限制。普通接口是整个请求的耗时上限,流式接口是两次收到数据之间的最大间隔。 |
84
+ | `headers` | `Record<string, string>` | 无 | 每个请求都附带的请求头。 |
85
+ | `fetch` | `(url, init) => Promise<Response>` | 全局 `fetch` | 自定义 fetch,例如需要走 HTTP 代理时使用(见下文)。 |
86
+
87
+ 每个方法的最后一个参数都可以传单次请求的选项:`{ headers, signal, timeout }`。`signal` 是 `AbortSignal`,用于主动取消请求。
88
+
89
+ ## 方法一览
90
+
91
+ | 方法 | 接口 | 返回值 |
92
+ | --- | --- | --- |
93
+ | `chatGenerate(req)` | `POST /api/chat/generate` | `ChatResponse`:`{ provider, model_name, text }` |
94
+ | `generateImage(req)` | `POST /api/images/generate` | `ImageGenerateResponse`:`{ provider, model_name, images: [{ image_url, text }], text }` |
95
+ | `generateImageStream(req, { onProgress, onEvent })` | `POST /api/images/generate/stream`(SSE) | 同 `generateImage` |
96
+ | `nbWritePrompt(req)` | `POST /api/nano_banana/write_prompt` | `ImageGenerateResponse`,改写后的提示词通常在 `text` 字段 |
97
+ | `generateVideo(req)` | `POST /api/videos/generate` | `VideoGenerateResult`:`{ video_id, provider, model_name, status }` |
98
+ | `queryVideoResult(req)` | `POST /api/videos/query_result` | `VideoQueryResult`:`{ video_id, provider, status, err_msg, video: { video_url, duration, resolution } }` |
99
+
100
+ 请求字段:
101
+
102
+ - **`chatGenerate`**:`prompt`(必填)、`system_instruction`、`provider`、`model_name`、`image_inputs`、`generation_config`。
103
+ - **图片接口**:`prompt`(必填)、`system_instruction`、`provider`、`model_name`(SDK 默认 `nano-banana`)、`image_inputs`、`aspect_ratio`、`number`、`response_type`(`auto` / `url` / `base64`)、`generation_config`、`fallback_provider`、`fallback_model_name`、`timeout`。
104
+ - **`generateVideo`**:`prompt`(必填)、`negative_prompt`、`provider`(SDK 默认 `doubao`)、`model_name`(SDK 默认 `seedance-2`)、`system_instruction`、`image_inputs`、`reference_media_inputs`、`resolution`(如 `1280x720`)、`duration`(秒)、`callback_url`、`generate_audio`、`generation_config`、`timeout`。
105
+ - `image_inputs`:图生视频的首帧、尾帧,`role` 取 `first_frame` / `last_frame`。
106
+ - `reference_media_inputs`:参考生视频的素材,`{ media_url, category }`,`category` 取 `image` / `video` / `audio`。
107
+ - **`queryVideoResult`**:`video_id`(必填)、`provider`。
108
+
109
+ 其他说明:
110
+
111
+ - 值为 `null` / `undefined` 的顶层字段不会发送,由服务端使用默认值。
112
+ - 图片、视频的 URL 字段都可以传 `http(s)` 地址,也可以传 `data:<mime>;base64,...`。
113
+ - 请求体里的 `timeout` 是服务端轮询上游结果的超时(秒),和客户端选项里的 `timeout`(毫秒)无关。
114
+ - `provider`、`model_name`、`generation_config` 的取值见下文。
115
+
116
+ ## 错误处理
117
+
118
+ | 错误类 | 何时抛出 | 主要属性 |
119
+ | --- | --- | --- |
120
+ | `APIRequestError` | 服务端返回非 2xx 状态码,或流式接口收到 `error` 事件 | `status`:HTTP 状态码<br>`detail`:服务端 `detail` 字段原值<br>`body`:解析后的响应体,不是 JSON 时为原始文本 |
121
+ | `APITimeoutError` | 超过 `timeout` | `timeout`(毫秒) |
122
+ | `APIConnectionError` | 没拿到响应:DNS 失败、连接被拒、连接中断等 | `cause`:底层原始错误 |
123
+ | `AIProxyError` | 以上所有错误的基类;也用于其他异常,比如流结束时没收到结果 | |
124
+
125
+ `APITimeoutError` 继承自 `APIConnectionError`。用户通过 `signal` 主动取消时,抛出的是原生 `AbortError`,不会被包装。
126
+
127
+ `APIRequestError.message` 的格式是 `HTTP <状态码>: <原因>`,原因按下面的顺序取:
128
+
129
+ - 服务端的 `detail`,例如 `HTTP 401: Invalid API key.`。
130
+ - 参数校验失败(422)时,`detail` 是错误列表,会拼成一行,例如 `HTTP 422: body.prompt: Field required`;原始列表保留在 `err.detail` 中。
131
+ - 网关返回纯文本或 HTML 错误页时,取正文或 `<title>`,例如 `HTTP 502: 502 Bad Gateway`。
132
+
133
+ ```js
134
+ import { AIProxyClient, AIProxyError, APIConnectionError, APIRequestError, APITimeoutError } from "wx_ai_proxy_client";
135
+
136
+ try {
137
+ await client.generateImage({ prompt: "a cat", model_name: "nano-banana-pro" });
138
+ } catch (err) {
139
+ if (err instanceof APIRequestError) {
140
+ // 服务端返回的错误
141
+ console.error(err.status, err.detail);
142
+ if (err.status === 401) { /* API Key 无效或已过期 */ }
143
+ if (err.status === 422) { /* 请求参数不合法,err.detail 为错误列表 */ }
144
+ } else if (err instanceof APITimeoutError) {
145
+ console.error("请求超时", err.timeout);
146
+ } else if (err instanceof APIConnectionError) {
147
+ console.error("网络错误", err.cause);
148
+ } else if (err instanceof AIProxyError) {
149
+ console.error("SDK 错误", err.message);
150
+ } else {
151
+ throw err; // AbortError 或业务代码自身的异常
152
+ }
153
+ }
154
+ ```
155
+
156
+ 服务端常见的错误码:
157
+
158
+ | 状态码 | 场景 |
159
+ | --- | --- |
160
+ | 400 | 参数错误,例如 provider 不支持(`Unknown provider ...`)、该 provider 不支持所调用的功能(如 `write_prompt`、参考生视频)、`fallback_provider` 与 `fallback_model_name` 数量不一致、输入图片格式不支持。 |
161
+ | 401 | 缺少 API Key(`Missing API key.`)、无效(`Invalid API key.`)或已过期(`API key has expired.`)。 |
162
+ | 422 | 请求参数校验失败,例如缺少 `prompt`、字段类型不对。 |
163
+ | 500 | 上游生成失败,`detail` 为失败原因,例如 `generate image failed`。 |
164
+ | 502 / 504 | 网关错误、上游返回的错误或上游超时。 |
165
+
166
+ ## 流式生成图片
167
+
168
+ 图片生成可能要好几分钟,容易被中间代理按读超时断开,这时可以用 `generateImageStream`。
169
+
170
+ 服务端会立刻建立 SSE 连接,每隔约 10 秒推送一次 `progress` 心跳。最终结果放在 `result` 事件里,结构和 `generateImage` 相同。流式接口的 `timeout` 指两次收到数据之间的最大间隔,所以总耗时可以超过 `timeout`。
171
+
172
+ ```js
173
+ const res = await client.generateImageStream(
174
+ { prompt: "a banana spaceship", provider: "google", model_name: "nano-banana-pro" },
175
+ {
176
+ onProgress: (data) => console.log("生成中,已耗时", data.elapsed, "秒"),
177
+ onEvent: ({ event, data }) => {}, // 可选:接收 start / progress / result / error 所有事件
178
+ timeout: 60_000,
179
+ },
180
+ );
181
+ ```
182
+
183
+ 流式接口的错误和普通接口一致:
184
+
185
+ - 建立流之前的错误抛 `APIRequestError`,例如 401,以及 provider 不支持、fallback 配置不一致等参数错误返回的 400(这类错误不会走 `error` 事件)。
186
+ - 生成过程中的 `error` 事件抛 `APIRequestError`,`status` 取事件里的 `status_code`。
187
+ - 流意外结束、没有收到 `result` 时抛 `AIProxyError`。
188
+ - `onProgress` / `onEvent` 回调自身抛出的异常会原样传出。
189
+
190
+ ## 取消请求与 HTTP 代理
191
+
192
+ ```js
193
+ // 主动取消
194
+ const controller = new AbortController();
195
+ setTimeout(() => controller.abort(), 5_000);
196
+ await client.generateImage({ prompt: "a cat" }, { signal: controller.signal });
197
+
198
+ // 走 HTTP 代理(npm install undici)
199
+ import { ProxyAgent, fetch as undiciFetch } from "undici";
200
+ const dispatcher = new ProxyAgent("http://127.0.0.1:7890");
201
+ const proxied = new AIProxyClient({
202
+ apiKey: process.env.AI_PROXY_API_KEY,
203
+ fetch: (url, init) => undiciFetch(url, { ...init, dispatcher }),
204
+ });
205
+ ```
206
+
207
+ <!-- 以下「provider 与 model_name 取值」「generation_config 说明」两节与 Python SDK 的 README 保持一致 -->
208
+
209
+ ## provider 与 model_name 取值
210
+
211
+ 基本规则:
212
+
213
+ - **`provider` 决定调用哪个上游。** 不区分大小写,首尾空格会被去掉;不传或传空字符串时使用该接口的默认值。传了不支持的值会直接返回 400(`Unknown provider '...'. Supported: ...`),不会调用任何上游。
214
+ - **`model_name` 推荐使用下表的通用模型名。** 服务端会根据 provider、是否有输入图片、是否为参考生视频,自动换成上游真实的模型 ID。
215
+ - **不在表中的 `model_name` 会原样透传给上游。** 所以也可以直接写上游的模型 ID,例如 `doubao-seedream-4-5-251128`。
216
+ - **以服务端实际配置为准。** 映射关系配置在服务端的 `model_names.yaml` 里,支持热更新;下表是编写本文档时(2026-10)的配置。
217
+
218
+ ### 图片接口(generateImage / generateImageStream / nbWritePrompt)
219
+
220
+ | provider | 上游 | 说明 |
221
+ | --- | --- | --- |
222
+ | `google`(默认) | Google Gemini 官方 API | |
223
+ | `chunqiu` | Gemini 第三方渠道 | 用法同 `google`。 |
224
+ | `openrouter` | OpenRouter | 只使用 `aspect_ratio`,忽略 `generation_config`。 |
225
+ | `falai` | fal.ai | |
226
+ | `kie` | kie.ai | 忽略 `aspect_ratio`、`number` 和 `generation_config`。 |
227
+ | `openai` | OpenAI gpt-image | |
228
+ | `302ai` | 302.AI | OpenAI 兼容接口,用法同 `openai`。 |
229
+ | `baidu` | 百度 AI 网关 | OpenAI 兼容接口,用法同 `openai`。没有配置通用名,`model_name` 直接传网关的模型 ID。 |
230
+ | `doubao` | 火山方舟 Seedream | |
231
+ | `qcloud` | 腾讯云点播 AIGC 生图 | |
232
+
233
+ | model_name(通用名) | 支持的 provider | 对应模型 |
234
+ | --- | --- | --- |
235
+ | `nano-banana` | google、chunqiu、openrouter、falai、kie、qcloud | Gemini 2.5 Flash Image(SDK 默认值) |
236
+ | `nano-banana-pro` | google、chunqiu、openrouter、falai、kie、qcloud | Gemini 3 Pro Image |
237
+ | `nano-banana-2` | google、qcloud | Gemini 3.1 Flash Image |
238
+ | `image-1` | openai、falai | gpt-image-1 |
239
+ | `image-2` | openai、falai、qcloud、302ai | gpt-image-2 |
240
+ | `image-2.5`、`image-2.5-flare` | openai、falai、qcloud | gpt-image-2.5 flare(两个名字等价) |
241
+ | `image-2.5-sunburst` | openai、falai、qcloud | gpt-image-2.5 sunburst |
242
+ | `seedream-4-0`、`seedream-4-5`、`seedream-5-0-lite` | doubao | Seedream 4.0 / 4.5 / 5.0 lite |
243
+
244
+ 另外两点:
245
+
246
+ - **写提示词接口**:目前只有 `google`(含 `chunqiu`)实现了 `nbWritePrompt`,其他 provider 返回 400。
247
+ - **失败自动切换**:`fallback_provider` / `fallback_model_name` 可以用英文逗号分隔多个备选,按顺序尝试。例如 `provider: "google", fallback_provider: "falai,kie"`。只填其中一个时,另一个沿用主请求的值;两个都填时数量必须一致。备选 provider 会在调用任何上游之前校验,数量不一致或写了不支持的 provider 都直接返回 400。
248
+
249
+ ### 视频接口(generateVideo / queryVideoResult)
250
+
251
+ | provider | 上游 | 说明 |
252
+ | --- | --- | --- |
253
+ | `openai` | OpenAI Sora | 服务端默认值:直接调用 HTTP 接口且不传 provider 时使用。 |
254
+ | `falai` | fal.ai | 也可以写别名 `fal`;返回结果里的 provider 是 `falai`。 |
255
+ | `kie` | kie.ai | |
256
+ | `doubao` | 火山方舟 Seedance | SDK 默认值:`VideoGenerateRequest` 不传 provider 时使用。 |
257
+ | `pollo` | Pollo AI | |
258
+ | `qcloud` | 腾讯云 | Seedance 系列走 SE 接口,Hailuo、Vega 等走点播 AIGC 接口。 |
259
+ | `minimax` | MiniMax 海螺官方 | |
260
+ | `metaso` | 秘塔(MiniMax 兼容接口) | 用法同 `minimax`。 |
261
+
262
+ | model_name(通用名) | 支持的 provider |
263
+ | --- | --- |
264
+ | `sora-2`(服务端默认)、`sora-2-pro` | openai、falai、kie |
265
+ | `kling-2-5` | falai、kie |
266
+ | `kling-v3` | pollo |
267
+ | `seedance-1-5-pro` | doubao |
268
+ | `seedance-2`(SDK 默认)、`seedance-2-fast` | doubao、kie、falai、pollo、qcloud |
269
+ | `seedance-2-mini` | doubao、kie、falai、qcloud |
270
+ | `seedance-2.5` | doubao、falai、qcloud |
271
+ | `minimax-h3` | minimax、metaso、qcloud、falai、kie |
272
+ | `minimax-h3-max` | qcloud、falai |
273
+ | `vega-lite` | qcloud |
274
+
275
+ 参考生视频(`reference_media_inputs`)的支持情况:
276
+
277
+ - **支持**:`doubao`、`qcloud`(`minimax-h3-max` 除外)、`minimax`、`kie`(seedance-2 系列、minimax-h3)、`pollo`(seedance-2 系列)、`falai`(seedance-2 系列、minimax-h3 系列)。
278
+ - **忽略**:`falai` 的其他模型会忽略参考素材。
279
+ - **报错**:`openai` 等不支持参考模式的 provider,传了会返回 400。
280
+
281
+ 查询任务结果时,`provider` 必须与创建任务时返回的 `provider` 一致。
282
+
283
+ ### 对话接口(chatGenerate)
284
+
285
+ - **`provider`**:目前只支持 `google`,传其他值返回 400。
286
+ - **`model_name`**:直接写 Gemini 的模型 ID,默认 `gemini-2.5-pro`,也可以用 `gemini-2.5-flash` 等。
287
+
288
+ ## generation_config 说明
289
+
290
+ `generation_config` 是一个可选的对象,用来传各上游特有的参数。使用时注意:
291
+
292
+ - **只认识自己的 key**:每个 provider 只读取自己认识的 key,其余的会被忽略,不会报错。所以 key 拼错也没有任何提示。
293
+ - **key 不通用**:不同 provider 的 key 互不通用。配置了 fallback 时,同一份 `generation_config` 会按每个备选 provider 的规则分别解析。
294
+ - **原样转发**:除特别说明外,值都原样转给上游,取值范围以上游文档为准。
295
+ - **通用字段用顶层参数**:`duration`、`resolution`、`generate_audio`、`number` 等通用字段请用顶层参数,`generation_config` 一般无法覆盖它们(例外情况在下文标出)。
296
+
297
+ ```js
298
+ // 对话:限制输出长度并要求返回 JSON
299
+ await client.chatGenerate({
300
+ prompt: "列出三种水果",
301
+ generation_config: { temperature: 0.2, max_output_tokens: 512, response_mime_type: "application/json" },
302
+ });
303
+
304
+ // Gemini 生图:2K 分辨率。注意 image_config 会替换顶层 aspect_ratio,需要写在一起
305
+ await client.generateImage({
306
+ prompt: "a cat",
307
+ model_name: "nano-banana-pro",
308
+ generation_config: { image_config: { aspect_ratio: "16:9", image_size: "2K" } },
309
+ });
310
+
311
+ // gpt-image:高质量、指定尺寸
312
+ await client.generateImage({
313
+ prompt: "a cat",
314
+ provider: "openai",
315
+ model_name: "image-2",
316
+ generation_config: { quality: "high", image_size: "1536x1024" },
317
+ });
318
+
319
+ // fal 上的 seedance 视频:固定随机种子
320
+ await client.generateVideo({
321
+ prompt: "a dog running",
322
+ provider: "falai",
323
+ model_name: "seedance-2",
324
+ generation_config: { seed: 42 },
325
+ });
326
+ ```
327
+
328
+ ### 对话(chat)
329
+
330
+ `google` 下,`generation_config` 等同于 Gemini SDK 的 `GenerateContentConfig`。key 必须用 snake_case(如 `max_output_tokens`),驼峰写法会被忽略。常用 key:
331
+
332
+ | key | 说明 |
333
+ | --- | --- |
334
+ | `temperature` / `top_p` / `top_k` | 采样参数。 |
335
+ | `max_output_tokens` | 最大输出 token 数。 |
336
+ | `response_mime_type` / `response_schema` | 结构化输出,例如 `"application/json"` 配合 JSON Schema。 |
337
+ | `thinking_config` | 思考配置,例如 `{ "thinking_budget": 0 }` 关闭思考。 |
338
+ | `seed`、`stop_sequences`、`safety_settings` 等 | 其他 `GenerateContentConfig` 字段。 |
339
+
340
+ 注意两点:
341
+
342
+ - `generation_config.system_instruction` 会覆盖顶层的 `system_instruction`。
343
+ - 参数类型不合法时,服务端返回 500。
344
+
345
+ ### 图片(images)
346
+
347
+ | provider | 支持的 key | 说明 |
348
+ | --- | --- | --- |
349
+ | `google` / `chunqiu` | 任意 `GenerateContentConfig` 字段 | 详见本表下方。 |
350
+ | `falai` | `image_size`、`quality` | `image_size` 用 fal 的尺寸枚举(如 `square_hd`、`landscape_16_9`)或 `{ "width": 1024, "height": 768 }`,以对应模型的 fal 文档为准。`quality` 用于 gpt-image 类模型(`low` / `medium` / `high`)。fal 生图**不使用**顶层 `aspect_ratio`,尺寸只能通过 `image_size` 控制。 |
351
+ | `openai` / `302ai` / `baidu` | `quality`、`image_size`(或 `size`) | `quality`:`low` / `medium` / `high` / `auto`。`image_size`:`"1536x1024"` 或 `{ "width": 1536, "height": 1024 }`,优先级高于顶层 `aspect_ratio`;顶层 `aspect_ratio` 只会映射成 `1024x1024`、`1024x1536`、`1536x1024` 之一。 |
352
+ | `doubao` | `tools` | 例如 `[{ "type": "web_search" }]` 开启联网搜索。尺寸由顶层 `aspect_ratio` 决定,组图数量由 `number` 决定。 |
353
+ | `qcloud` | 见下表 | |
354
+ | `openrouter`、`kie` | 无 | 忽略。 |
355
+
356
+ `google` / `chunqiu` 常用的 key:
357
+
358
+ - **`image_config`**:例如 `{ "aspect_ratio": "16:9", "image_size": "2K" }`。`image_size` 取 `1K` / `2K` / `4K`,以 Gemini 文档为准。
359
+ - **其他**:`temperature`、`seed`、`response_modalities`(默认 `["Image", "Text"]`)。
360
+
361
+ 注意两个优先级:
362
+
363
+ - 传了 `image_config` 会**整体替换**由顶层 `aspect_ratio` 生成的配置,所以要把 `aspect_ratio` 一并写进 `image_config`。
364
+ - 顶层 `system_instruction` 优先于这里的同名 key。
365
+
366
+ `qcloud` 生图:
367
+
368
+ | key | 说明 |
369
+ | --- | --- |
370
+ | `quality` | 仅 `image-2` 系列(GPT 生图)有效,用于选择档位。`image-2` 支持 `low`(默认)/ `medium` / `high`;`image-2.5*` 另外支持 `xhigh`、`xxhigh`。 |
371
+ | `negative_prompt` | 反向提示词。 |
372
+ | `enhance_prompt` | 提示词增强,原样传给接口(`Enabled` / `Disabled`)。 |
373
+ | `region` | 输入区域(`InputRegion`)。 |
374
+ | `seed` | 随机种子(整数)。 |
375
+ | `image_size` / `size` | 输出尺寸,`"2048x2048"` 或 `{ "width": 2048, "height": 2048 }`。 |
376
+ | `sequential_image_generation` | 组图模式。 |
377
+ | `storage_mode` | 存储模式,默认 `Temporary`。 |
378
+ | `person_generation` | 人物生成策略,默认 `AllowAdult`。 |
379
+ | `input_compliance_check` / `output_compliance_check` | 输入 / 输出合规检查,默认 `Disabled`。 |
380
+
381
+ qcloud 的宽高比只能用顶层 `aspect_ratio`,服务端会就近取支持的比例;`number` 对 qcloud 不生效。
382
+
383
+ ### 视频(videos)
384
+
385
+ | provider | 支持的 key | 说明 |
386
+ | --- | --- | --- |
387
+ | `falai` | seedance 系列:`seed`、`bitrate_mode`<br>minimax-h3 系列:`seed`、`prompt_expansion_mode`(默认 `balanced`)、`enable_safety_checker` | sora-2、kling 忽略 `generation_config`。 |
388
+ | `doubao` | `service_tier`、`execution_expires_after` | 例如 `{ "service_tier": "flex" }` 使用离线推理;`execution_expires_after` 为任务过期秒数。取值以火山方舟文档为准。 |
389
+ | `pollo` | seedance 首尾帧模式:`seed`、`web_search`<br>seedance 参考模式:`video_num`、`unlimited`<br>kling-v3:`mode`、`multi_shot` | kling-v3 的 `mode` 取 `std` / `pro` / `4k`,优先于根据 `resolution` 推断的档位。 |
390
+ | `qcloud`(seedance 系列) | `seed`、`service_tier`、`execution_expires_after`、`safety_identifier` | |
391
+ | `qcloud`(minimax-h3、minimax-h3-max、vega-lite 等点播 AIGC 模型) | 见下表 | |
392
+ | `minimax` / `metaso` | `ratio`、`resolution`、`aigc_watermark` | 覆盖服务端根据顶层 `resolution` 推断出的档位(如 `768P`、`2K`)和比例;`aigc_watermark` 默认 `false`。 |
393
+ | `openai`、`kie` | 无 | 忽略。 |
394
+
395
+ `qcloud` 点播 AIGC 视频:
396
+
397
+ | key | 说明 |
398
+ | --- | --- |
399
+ | `negative_prompt` | 反向提示词,顶层 `negative_prompt` 优先。 |
400
+ | `enhance_prompt` | 提示词增强。 |
401
+ | `seed` | 随机种子。 |
402
+ | `aspect_ratio` | 输出宽高比(如 `16:9`、`adaptive`),覆盖根据 `resolution` 推断的比例;首尾帧模式下不生效。 |
403
+ | `logo_add` | 是否加水印,默认否。 |
404
+ | `storage_mode` | 存储模式,默认 `Temporary`。 |
405
+ | `media_name` | 输出媒体名称。 |
406
+ | `enhance_switch`、`frame_interpolate`、`off_peak`、`input_compliance_check`、`output_compliance_check` | 开关项。 |
407
+ | `input_region`、`procedure`、`session_id`、`session_context`、`scene_type`、`tasks_priority` | 透传给点播接口的同名参数。 |
408
+ | `ext_info` / `additional_parameters` | 扩展参数:`ext_info` 原样作为 `ExtInfo`;`additional_parameters` 会包装成 `{ "AdditionalParameters": ... }`。两者同时传时 `ext_info` 优先。 |
409
+
410
+ 开关类 key(含 `logo_add`)传 `true`,或字符串 `enabled` / `true` / `1` / `yes`(不区分大小写)表示开启,其他值都表示关闭。
@@ -0,0 +1,63 @@
1
+ import type { ChatRequest, ChatResponse, ImageGenerateRequest, ImageGenerateResponse, ImageStreamEvent, VideoGenerateRequest, VideoGenerateResult, VideoQueryRequest, VideoQueryResult } from "./types.js";
2
+ export declare const DEFAULT_BASE_URL = "https://ai-api-proxy.segapi.com";
3
+ /** 默认超时 3 分钟:图片生成通常要几十秒到数分钟 */
4
+ export declare const DEFAULT_TIMEOUT = 180000;
5
+ export type FetchLike = (input: string, init: RequestInit) => Promise<Response>;
6
+ export interface AIProxyClientOptions {
7
+ /** 服务地址,默认 https://ai-api-proxy.segapi.com */
8
+ baseUrl?: string;
9
+ /** 以 `Authorization: Bearer <apiKey>` 发送 */
10
+ apiKey?: string;
11
+ /**
12
+ * 超时(毫秒),默认 180000,0 表示不限制。
13
+ * 普通接口为整个请求的耗时上限;流式接口为两次收到数据之间的最大间隔。
14
+ */
15
+ timeout?: number;
16
+ /** 每个请求都附带的自定义请求头 */
17
+ headers?: Record<string, string>;
18
+ /** 自定义 fetch 实现,例如需要走 HTTP 代理,或运行在没有全局 fetch 的 Node.js < 18 */
19
+ fetch?: FetchLike;
20
+ }
21
+ export interface RequestOptions {
22
+ /** 本次请求额外的请求头,同名时覆盖客户端级别的设置 */
23
+ headers?: Record<string, string>;
24
+ /** 用于主动取消请求;取消时抛出原生 AbortError */
25
+ signal?: AbortSignal;
26
+ /** 覆盖客户端级别的 timeout(毫秒) */
27
+ timeout?: number;
28
+ }
29
+ export interface ImageStreamOptions extends RequestOptions {
30
+ /** 收到 progress 心跳事件时调用,可以是 async 函数 */
31
+ onProgress?: (data: Record<string, unknown>) => unknown;
32
+ /** 收到任意事件(start / progress / result / error)时调用,可以是 async 函数 */
33
+ onEvent?: (event: ImageStreamEvent) => unknown;
34
+ }
35
+ /**
36
+ * AI API Proxy 客户端,所有方法均返回 Promise。
37
+ *
38
+ * ```ts
39
+ * const client = new AIProxyClient({ apiKey: "xxx" });
40
+ * const res = await client.generateImage({ prompt: "a cat", provider: "google", model_name: "nano-banana" });
41
+ * ```
42
+ */
43
+ export declare class AIProxyClient {
44
+ #private;
45
+ readonly baseUrl: string;
46
+ readonly timeout: number;
47
+ constructor(options?: AIProxyClientOptions);
48
+ /** POST /api/chat/generate:文本/多模态对话 */
49
+ chatGenerate(request: ChatRequest, options?: RequestOptions): Promise<ChatResponse>;
50
+ /** POST /api/images/generate:生成图片,model_name 不传时默认 nano-banana */
51
+ generateImage(request: ImageGenerateRequest, options?: RequestOptions): Promise<ImageGenerateResponse>;
52
+ /**
53
+ * POST /api/images/generate/stream:generateImage 的流式(SSE)版本,适合耗时数分钟的生成。
54
+ * 服务端周期性下发 progress 心跳保活,最终结果与 generateImage 相同。
55
+ */
56
+ generateImageStream(request: ImageGenerateRequest, options?: ImageStreamOptions): Promise<ImageGenerateResponse>;
57
+ /** POST /api/nano_banana/write_prompt:改写/生成提示词,结果通常在 text 字段 */
58
+ nbWritePrompt(request: ImageGenerateRequest, options?: RequestOptions): Promise<ImageGenerateResponse>;
59
+ /** POST /api/videos/generate:创建视频生成任务(异步),返回 video_id;provider / model_name 不传时默认 doubao / seedance-2 */
60
+ generateVideo(request: VideoGenerateRequest, options?: RequestOptions): Promise<VideoGenerateResult>;
61
+ /** POST /api/videos/query_result:查询视频任务状态与结果 */
62
+ queryVideoResult(request: VideoQueryRequest, options?: RequestOptions): Promise<VideoQueryResult>;
63
+ }