dsh-image-video 0.3.1

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/lib/index.d.ts ADDED
@@ -0,0 +1,862 @@
1
+ import z from "@deepseek-ai/schemastery";
2
+ import * as _deepseek_ai_dsh_tools0 from "@deepseek-ai/dsh-tools";
3
+ import { Context } from "@deepseek-ai/cordis";
4
+ import { AttachmentStore } from "@deepseek-ai/dsh-attachment";
5
+ import * as node_http0 from "node:http";
6
+ import { IncomingMessage, ServerResponse } from "node:http";
7
+
8
+ //#region src/config.d.ts
9
+ /** 支持的生成服务商。minimax 为 MiniMax 官方平台直连(仅视频),threerouter 为聚合器(所有模型)。 */
10
+ type Provider = 'threerouter' | 'wanx' | 'minimax' | 'seedance';
11
+ /** 单个服务商的凭证与自定义接口地址。 */
12
+ interface ProviderCredentials {
13
+ /** 服务商 API Key;切换 provider 后对应 key 立即生效。 */
14
+ apiKey: string;
15
+ /** 自定义接口地址,留空使用服务商默认端点。 */
16
+ baseURL?: string;
17
+ }
18
+ /** 水印位置(四角之一)。 */
19
+ type WatermarkPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
20
+ /**
21
+ * 品牌水印后处理配置。所有尺寸类参数都是**相对图片宽/高的比例**,
22
+ * 保证同一套配置对不同尺寸出图观感一致。
23
+ */
24
+ interface WatermarkConfig {
25
+ /** 是否对最终图片合成品牌水印(关闭时图片流程完全不受影响)。 */
26
+ enabled: boolean;
27
+ /** 水印文字。 */
28
+ text: string;
29
+ /** 主文字不透明度(0-1)。 */
30
+ opacity: number;
31
+ /** 水印位置:四角之一。 */
32
+ position: WatermarkPosition;
33
+ /** 字号占图片宽度的比例。 */
34
+ fontSizeRatio: number;
35
+ /** 水平留白占图片宽度的比例。 */
36
+ marginXRatio: number;
37
+ /** 垂直留白占图片高度的比例。 */
38
+ marginYRatio: number;
39
+ /** 是否给水印加柔光(浅色底图上也看得见)。 */
40
+ glowEnabled: boolean;
41
+ /** 柔光颜色。 */
42
+ glowColor: string;
43
+ /** 柔光半径占字号的比例。 */
44
+ glowBlurRatio: number;
45
+ }
46
+ interface Config {
47
+ /** 当前激活的服务商,切换后立即生效(HMR)。 */
48
+ provider: Provider;
49
+ /** Threerouter 凭证;provider=threerouter 时使用(支持图片+视频)。 */
50
+ threerouter: ProviderCredentials;
51
+ /** 万象(wanx)凭证;provider=wanx 时使用。 */
52
+ wanx: ProviderCredentials;
53
+ /** MiniMax 官方平台凭证;provider=minimax 时使用(图片与视频)。 */
54
+ minimax: ProviderCredentials;
55
+ /** Seedance2.5 凭证;provider=seedance 时使用。 */
56
+ seedance: ProviderCredentials;
57
+ /** 默认图片服务商;留空跟随激活服务商。 */
58
+ defaultImageProvider: '' | Provider;
59
+ /** 默认视频服务商;留空跟随激活服务商,adapter 使用其内置默认模型。 */
60
+ defaultVideoProvider: '' | Provider;
61
+ /** 默认图片模型;留空使用 adapter 内置默认模型。 */
62
+ defaultImageModel: string;
63
+ /** 默认视频模型;留空使用 adapter 内置默认模型。 */
64
+ defaultVideoModel: string;
65
+ /** 默认图片尺寸,形如 "1024*1024"。 */
66
+ defaultImageSize: string;
67
+ /** 默认视频时长(秒),上限 30;具体模型能力由上游校验。 */
68
+ defaultVideoDuration: number;
69
+ /**
70
+ * 图片提交传输方式:
71
+ * - `auto`:优先异步网关(幂等 + 超时找回),服务商不支持或探测到不可用时降级同步;
72
+ * - `async`:强制异步,端点不可用即响亮失败(上线验收口径);
73
+ * - `sync`:强制同步单次提交(无幂等,仅保证「不自动重提」)。
74
+ */
75
+ imageTransport: 'auto' | 'async' | 'sync';
76
+ /**
77
+ * 提交结果未知(超时/断连/5xx 且按幂等键反查无果)后的策略:
78
+ * - `fail`:不自动重提,响亮失败并回报 request_id(默认,最保守);
79
+ * - `resubmit-same-key`:用同一个幂等键再提交一次(服务端按键去重,不会重复生成)。
80
+ */
81
+ imageUnknownStatePolicy: 'fail' | 'resubmit-same-key';
82
+ /** 单次 HTTP 请求超时(毫秒)。 */
83
+ timeoutMs: number;
84
+ /** 视频任务轮询间隔(毫秒)。 */
85
+ pollIntervalMs: number;
86
+ /** 视频任务整体超时(毫秒),超时后中止轮询。 */
87
+ pollTimeoutMs: number;
88
+ /** 可重试错误的最大重试次数(仅作用于幂等的读取类请求;生图提交永远不重试)。 */
89
+ retryTimes: number;
90
+ /** 生成媒体落地目录,相对路径基于进程 cwd 解析;插件启动时解析为绝对路径并打日志。 */
91
+ outputsDir: string;
92
+ /** 图片最终结果的品牌水印后处理。 */
93
+ watermark: WatermarkConfig;
94
+ }
95
+ /** 插件配置 schema,默认服务商为 threerouter(图片+视频统一入口),wanx/seedance 可选。 */
96
+ declare const Config: z<Config>;
97
+ /**
98
+ * 读取指定服务商的凭证,不校验 key 非空。供候选服务商构建时的 key 过滤
99
+ * (resolveModelCandidates 用它跳过未配置 key 的候选),不抛错。
100
+ */
101
+ //#endregion
102
+ //#region src/watermark.d.ts
103
+ /** 水印处理结果。 */
104
+ interface WatermarkResult {
105
+ /** 最终图片字节(失败时为原始字节)。 */
106
+ data: Uint8Array;
107
+ /** 最终图片 MIME 类型。 */
108
+ contentType: string;
109
+ /** 是否真的合成了水印(enabled=false / 文本为空 / 出错时为 false)。 */
110
+ applied: boolean;
111
+ /** 未合成时的原因说明(供结果层透明告知);正常合成时缺省。 */
112
+ note?: string;
113
+ }
114
+ /**
115
+ * 给图片加品牌水印。
116
+ * @param data - 模型返回的原始图片字节。
117
+ * @param contentType - 原始 MIME 类型(决定输出编码,保持与上游一致的格式)。
118
+ * @param config - 水印配置(enabled=false 时直接原样返回)。
119
+ * @returns 处理结果(含 applied / note,供结果层如实告知)。
120
+ */
121
+ declare function applyImageWatermark(data: Uint8Array, contentType: string, config: WatermarkConfig): Promise<WatermarkResult>;
122
+ /**
123
+ * 构造水印 SVG。导出供单测直接断言坐标/字号等几何决策,无需真的解码图片。
124
+ * @param width - 图片宽度(像素)。
125
+ * @param height - 图片高度(像素)。
126
+ * @param text - 水印文字(已 trim,非空)。
127
+ * @param config - 水印配置。
128
+ */
129
+ declare function buildWatermarkSvg(width: number, height: number, text: string, config: WatermarkConfig): string;
130
+ /**
131
+ * 计算字号:基准为 `宽度 × fontSizeRatio`,并保证估算文字宽度不超过
132
+ * 可用宽度(图片宽度减两侧留白)的 95%,避免窄图上水印横向溢出。
133
+ * @param text - 水印文字。
134
+ * @param width - 图片宽度。
135
+ * @param marginX - 单侧水平留白。
136
+ * @param fontSizeRatio - 字号占图片宽度的比例。
137
+ * @returns 最终字号(像素,至少 10px)。
138
+ */
139
+ declare function fitFontSize(text: string, width: number, marginX: number, fontSizeRatio: number): number;
140
+ //#endregion
141
+ //#region src/http-client.d.ts
142
+ /**
143
+ * 统一 HTTP 请求客户端:封装 fetch,分类异常,可配置重试。
144
+ * 鉴权失败、配额耗尽等不可重试错误立即抛出;超时、网络抖动按配置重试。
145
+ * @module dsh-image-video/http-client
146
+ */
147
+ /** 异常种类,区分可重试与不可重试。 */
148
+ type ErrorKind = 'auth' | 'quota' | 'task' | 'timeout' | 'network';
149
+ /** 所有生成相关错误的基类,携带友好中文提示与分类标记。 */
150
+ declare class GenerationError extends Error {
151
+ readonly kind: ErrorKind;
152
+ /** 是否值得重试:仅超时与网络抖动重试,鉴权/配额/任务逻辑错误立即失败。 */
153
+ readonly retryable: boolean;
154
+ /** 原始 HTTP 状态码,任务级错误可能为 undefined。 */
155
+ readonly status?: number;
156
+ /** 服务端 Retry-After 建议的等待时间(毫秒)。 */
157
+ readonly retryAfterMs?: number;
158
+ /**
159
+ * 服务端返回的机器可读错误码(形如 `{"error":{"code":"IDEMPOTENCY_IN_PROGRESS"}}`)。
160
+ * 生图事务靠它区分「提交未落地(可回退候选)」与「提交状态未知(绝不重提)」,
161
+ * 因此必须比 message 文本更可靠地保留下来。
162
+ */
163
+ readonly code?: string;
164
+ constructor(kind: ErrorKind, message: string, retryable: boolean, status?: number, retryAfterMs?: number, code?: string);
165
+ }
166
+ /** 服务端错误码:幂等键对应的首次提交仍在进行中(GateWay 异步图片契约)。 */
167
+
168
+ /**
169
+ * 判定错误是否为「异步图片端点在本环境不可用」:功能未开启(未配对象存储)或
170
+ * 该分组平台不支持 Images API。两者都在创建任务前返回 404,因此降级到同步
171
+ * 单次提交不会产生重复生成。
172
+ */
173
+ declare function isAsyncImageUnavailableError(err: unknown): boolean;
174
+ /** 判定错误是否为「同一幂等键首次提交仍在进行中」:任务已存在,应凭 request_id 找回而非重提。 */
175
+
176
+ /**
177
+ * 判定错误是否为「提交状态未知」——客户端无法确认请求是否已在服务端创建任务。
178
+ * 超时、连接中断、502/503 都属于此类:**绝不允许自动重提或换模型**,只能凭
179
+ * request_id 反查(见 image-transaction.ts)。
180
+ */
181
+ declare function isUnknownSubmitStateError(err: unknown): boolean;
182
+ /**
183
+ * 判定错误是否为「调用方主动取消」。取消同样可能发生在请求已抵达服务端之后,
184
+ * 因此不视为「未提交」——只是不再做任何自动动作(找回/重提都不做)。
185
+ */
186
+
187
+ /**
188
+ * 判定错误是否为「模型不被该服务商接受」类,供工具层在候选服务商间回退。
189
+ * 实测形态(2026-09):
190
+ * - threerouter:目录中无可用渠道的模型 → HTTP 503 capacity_error
191
+ * "No available media generation channels"(网关按模型找渠道,未知模型即无渠道);
192
+ * - threerouter:分组未开通生图 → HTTP 403 permission_error
193
+ * "Image generation is not enabled for this group"(文档语义:401=Key 无效,
194
+ * 403=无该分组/模型权限或未开通生图 allow_image_generation——属于「该候选
195
+ * 无法服务此请求」,应换下一候选,而非响亮终止);
196
+ * - 部分服务商:HTTP 400/404 + 模型不存在类消息("model not found" / "模型不存在");
197
+ * - 能力缺失:如「不支持图片生成」。
198
+ * 注意区分语义相近的参数级 400——如 "model X does not support duration 1s"
199
+ * (时长档位问题,模型本身可用),该类消息不命中本判定,不触发换家。
200
+ * 其余 5xx(无 capacity_error 语义)、Key 无效(401)、配额(429)、超时一律不成立:
201
+ * 响亮失败,避免用别家的 key 静默掩盖本服务商的配置问题。
202
+ */
203
+ declare function isModelNotAcceptedError(err: unknown): boolean;
204
+ /** 请求选项。 */
205
+ interface RequestOptions {
206
+ method: 'GET' | 'POST';
207
+ url: string;
208
+ headers: Record<string, string>;
209
+ /** JSON 请求体;GET 请求忽略。 */
210
+ body?: unknown;
211
+ /** 单次请求超时(毫秒)。 */
212
+ timeoutMs: number;
213
+ /** 最大重试次数(仅对可重试错误生效)。 */
214
+ retryTimes: number;
215
+ /** 取消信号,由调用方(任务管理器)传入。 */
216
+ signal?: AbortSignal;
217
+ }
218
+ /** 请求结果。 */
219
+ interface RequestResult {
220
+ ok: true;
221
+ status: number;
222
+ data: unknown;
223
+ headers: Headers;
224
+ }
225
+ /**
226
+ * 分类 HTTP 响应错误,生成友好中文提示。
227
+ * 内部实现,不在 execute 外部直接调用。通过 `classifyErrorForTest` 导出用于单元测试。
228
+ */
229
+ /**
230
+ * 解析 Retry-After 响应头为毫秒(支持秒数与 HTTP 日期两种形态),上限 180s。
231
+ * 导出供适配器读取 202/409 上的服务端建议轮询间隔。
232
+ */
233
+ //#endregion
234
+ //#region src/providers/types.d.ts
235
+ /** 图片生成请求参数(不传 image 为文生图,传入 image 为图生图/参考图编辑)。 */
236
+ interface ImageGenParams {
237
+ /** 客户端生成事务唯一 ID;服务端必须按此字段幂等。 */
238
+ requestId?: string;
239
+ /** 提示词。 */
240
+ prompt: string;
241
+ /** 图片尺寸,如 "1024x1024"(分隔符可能为 `*`,适配器经 normalizeImageSize 归一化)。 */
242
+ size: string;
243
+ /** 可选模型名,留空使用适配器默认模型。 */
244
+ model?: string;
245
+ /**
246
+ * 可选参考图,存在时走图生图:http(s) URL、data URL(本地路径已由调用方经
247
+ * media.resolveImageReference 统一解析),适配器只负责放到各自协议字段。
248
+ * 各家语义不同:threerouter /images/edits 按提示词编辑、方舟 Seedream 参考编辑、
249
+ * MiniMax 主体一致性(保留主体换场景)。
250
+ */
251
+ image?: string;
252
+ /**
253
+ * 多参考图(按调用方顺序):首图通常是底图,其余图片是编辑/身份参考。
254
+ * threerouter 适配器会以 `image_urls` 发给服务端;不支持多图的直连适配器
255
+ * 至少使用第一张图,保持旧版单图协议兼容。
256
+ */
257
+ images?: string[];
258
+ }
259
+ /** 视频生成请求参数(文生视频,带 image 时为首帧驱动的图生视频)。 */
260
+ interface VideoGenParams {
261
+ /** 提示词。 */
262
+ prompt: string;
263
+ /** 视频时长(秒),上限 10。 */
264
+ duration: number;
265
+ /** 可选宽高比,如 "16:9"。存在 image 时构图由首帧图片决定,适配器不传该字段。 */
266
+ aspectRatio?: string;
267
+ /** 可选模型名,留空使用适配器默认模型。 */
268
+ model?: string;
269
+ /**
270
+ * 可选首帧图片,存在时走图生视频:http(s) URL、data URL 或本地文件路径。
271
+ * 调用方经 media.resolveImageReference 统一解析后才传入,适配器只负责放到各自字段。
272
+ */
273
+ image?: string;
274
+ /**
275
+ * wan3.0-video 多关键帧:按时间点排列的参考图序列(如 position '0s' / '1s'…)。
276
+ * 调用方经 media.resolveVideoMedia 统一解析(压缩 + 转 data URL),
277
+ * 适配器按文档转换为 type/url;存在时 image 字段忽略。
278
+ */
279
+ media?: Array<{
280
+ url: string;
281
+ type?: string;
282
+ position?: string;
283
+ }>;
284
+ /** 可选分辨率档位,取值由服务商与模型决定(如 MiniMax-H3 支持 480P/768P/2K);留空用服务商默认。 */
285
+ resolution?: string;
286
+ }
287
+ /** 任务提交结果。 */
288
+ interface SubmitResult {
289
+ /** 任务 ID;同步接口返回空字符串。 */
290
+ taskId: string;
291
+ /** true 表示需要轮询查询,false 表示同步已返回结果。 */
292
+ async: boolean;
293
+ /** 同步接口直接返回的媒体 URL;async=false 时有值。 */
294
+ mediaUrl?: string;
295
+ /** 媒体类型,用于区分图片/视频渲染。 */
296
+ mediaType: 'image' | 'video';
297
+ /** true 表示请求携带的 duration 因模型不支持自定义时长被丢弃(结果层据此在 notes 注明)。 */
298
+ droppedDuration?: boolean;
299
+ /**
300
+ * 实际发给上游的模型名(含适配器内置默认的兜底结果)。结果层据此向用户
301
+ * 透明报告「这次到底用了哪个模型」,无需再靠配置推断。
302
+ */
303
+ model?: string;
304
+ /**
305
+ * 同步接口直接返回的 base64 图片字节(MiniMax image_generation 等)。
306
+ * 有值时结果层直接落盘,跳过 downloadAndSave 下载步骤。
307
+ */
308
+ mediaBase64?: {
309
+ data: string;
310
+ mediaType: string;
311
+ };
312
+ }
313
+ /** 任务查询结果。 */
314
+ type TaskQueryResult = {
315
+ status: 'pending' | 'running';
316
+ } | {
317
+ status: 'succeeded';
318
+ mediaUrl: string;
319
+ } | {
320
+ status: 'failed';
321
+ error: string;
322
+ };
323
+ /**
324
+ * 异步图片提交结果(202 Accepted 形态)。
325
+ * 与 {@link SubmitResult} 的区别:这里只有「任务已被接受」这一个事实,
326
+ * 结果图 URL 必须经轮询端点取得,因此不存在同步返回的 mediaUrl。
327
+ */
328
+ interface AsyncImageSubmit {
329
+ /** 网关任务 ID(`imgtask_…`),轮询与找回的唯一句柄。 */
330
+ taskId: string;
331
+ /** 本次提交实际使用的模型名(服务商回报或本地推断)。 */
332
+ model?: string;
333
+ /** 服务端回显的幂等键。 */
334
+ requestId?: string;
335
+ /** true = 服务端幂等回放(`X-Idempotency-Replayed: true`),本次没有新建任务。 */
336
+ replayed?: boolean;
337
+ /** 服务端建议的轮询间隔(`Retry-After` 秒);缺省用配置的轮询间隔。 */
338
+ retryAfterSec?: number;
339
+ }
340
+ /**
341
+ * 异步图片网关能力(可选):提交立即返回任务句柄、结果经轮询取得,
342
+ * 并支持「凭幂等键找回任务」——这是提交响应因超时/断连丢失后不重复
343
+ * 生成的唯一自救通道。只有实现该能力的服务商才允许配置 async 传输。
344
+ */
345
+ interface ImageAsyncCapability {
346
+ /** 提交一次图片生成任务,返回任务句柄(服务端保证同一幂等键只创建一次)。 */
347
+ submit(params: ImageGenParams, opts: HttpOpts): Promise<AsyncImageSubmit>;
348
+ /** 查询任务状态;图片任务与视频任务的查询端点可能不同。 */
349
+ query(taskId: string, opts: HttpOpts): Promise<TaskQueryResult>;
350
+ /** 凭幂等键找回原任务;未找到返回 undefined(不抛错,由上层按策略决定)。 */
351
+ findByRequest(requestId: string, opts: HttpOpts): Promise<{
352
+ taskId: string;
353
+ } | undefined>;
354
+ }
355
+ /** HTTP 请求选项子集,由工具层从 Config 解析后传入。 */
356
+ interface HttpOpts {
357
+ apiKey: string;
358
+ baseURL: string;
359
+ timeoutMs: number;
360
+ retryTimes: number;
361
+ signal?: AbortSignal;
362
+ }
363
+ /** 将 HttpOpts 转换为 RequestOptions。 */
364
+
365
+ /** 服务商适配器接口。 */
366
+ interface ProviderAdapter {
367
+ /** 提交文生图任务(同步语义:返回体即结果,或返回可轮询的异步任务句柄)。 */
368
+ submitImage(params: ImageGenParams, opts: HttpOpts): Promise<SubmitResult>;
369
+ /** 提交文生视频任务(始终异步)。 */
370
+ submitVideo(params: VideoGenParams, opts: HttpOpts): Promise<SubmitResult>;
371
+ /** 查询异步任务状态。 */
372
+ queryTask(taskId: string, opts: HttpOpts): Promise<TaskQueryResult>;
373
+ /**
374
+ * 异步图片网关能力(可选能力声明)。实现它的服务商才能接受 `imageTransport: async`:
375
+ * 提交即返回任务句柄、结果经 `query` 轮询、响应丢失时经 `findByRequest` 找回。
376
+ * 未实现时工具层按同步单次提交处理(仍然只提交一次、超时不重提)。
377
+ */
378
+ imageAsync?: ImageAsyncCapability;
379
+ }
380
+ /** 从 "1024x1024" 格式解析宽高。 */
381
+ //#endregion
382
+ //#region src/task-manager.d.ts
383
+ /** 轮询完成结果。 */
384
+ interface PollResult {
385
+ /** 媒体下载 URL。 */
386
+ mediaUrl: string;
387
+ /** 任务耗时(毫秒)。 */
388
+ elapsedMs: number;
389
+ }
390
+ /**
391
+ * 查询函数签名:可由适配器(视频/自带异步任务的服务商)或专门的图片任务查询
392
+ * 实现(网关 `/images/tasks/{id}`)提供。
393
+ */
394
+ type TaskQueryFn = (taskId: string, opts: HttpOpts) => Promise<TaskQueryResult>;
395
+ /**
396
+ * 任务管理器:管理所有进行中的生成任务轮询。
397
+ * 在 apply() 中实例化,通过 ctx.effect 注册卸载清理。
398
+ */
399
+ declare class TaskManager {
400
+ /** 进行中的任务,key 为 taskId。 */
401
+ private readonly active;
402
+ /** 配置引用。 */
403
+ private readonly config;
404
+ constructor(ctx: Context, config: Config);
405
+ /**
406
+ * 轮询任务直到完成、失败或超时。
407
+ * 使用 AbortSignal 支持外部取消(插件卸载或工具调用超时)。
408
+ * 轮询过程中不产生中间输出,仅最终结果返回给模型,不阻塞对话上下文。
409
+ * @param taskId - 服务商返回的任务 ID。
410
+ * @param query - 查询实现:适配器实例(用其 queryTask)或直接的查询函数。
411
+ * @param httpOpts - HTTP 请求选项(含凭证与超时)。
412
+ * @param externalSignal - 外部取消信号(工具执行上下文的 exec.signal)。
413
+ * @returns 媒体 URL 与耗时。
414
+ * @throws {GenerationError} 任务失败、超时或被取消(超时错误带 task_id)。
415
+ */
416
+ pollUntilDone(taskId: string, query: ProviderAdapter | TaskQueryFn, httpOpts: HttpOpts, externalSignal?: AbortSignal): Promise<PollResult>;
417
+ /** 获取当前进行中的任务数,供状态展示。 */
418
+ get activeCount(): number;
419
+ /**
420
+ * 判定查询阶段的错误是否属于「瞬时故障、值得继续轮询」。
421
+ * 可重试分类(网络/超时/5xx/限流)与不可重试的鉴权/参数错误区分开:
422
+ * 后者继续轮询只会白等,立即抛出。
423
+ */
424
+ private isTransientQueryError;
425
+ /** 可被取消的延时;信号触发时立即 reject。 */
426
+ private sleep;
427
+ }
428
+ //#endregion
429
+ //#region src/image-transaction.d.ts
430
+ /** 图片提交传输方式:async = 网关异步任务(有幂等与找回),sync = 同步端点(无幂等)。 */
431
+ type ImageTransport = 'async' | 'sync';
432
+ /**
433
+ * 提交状态未知(超时/断连/5xx 且找回无果)后的策略。
434
+ * - `fail`(默认):不自动重提,响亮失败并给出 requestId,由用户决定是否重试。
435
+ * - `resubmit-same-key`:用**同一个幂等键**再提交一次。服务端保证同一键只创建
436
+ * 一个任务(回放原响应或返回 409 进行中),因此不会重复生成;仅 async 传输可用。
437
+ */
438
+ type UnknownStatePolicy = 'fail' | 'resubmit-same-key';
439
+ /** 事务状态机取值。 */
440
+ type TransactionStatus = /** 已创建,尚未提交。 */
441
+ 'idle'
442
+ /** 提交请求已发出。 */ | 'submitting'
443
+ /** 服务端已接受任务(有 taskId)。 */ | 'accepted'
444
+ /** 提交结果未知:可能已创建任务,也可能没有——只能反查,不能重提。 */ | 'unknown'
445
+ /** 成功拿到结果。 */ | 'succeeded'
446
+ /** 明确失败:服务端在创建任务之前拒绝,或任务本身执行失败。 */ | 'failed';
447
+ /**
448
+ * 事务账本:一次 `generate_image` 调用对应一个实例,记录提交/找回/结果的
449
+ * 全部事实,作为结果元数据回给用户(「本次到底提交了几次」必须可核对)。
450
+ */
451
+ interface ImageTransaction {
452
+ /** 幂等键(服务端按 `Idempotency-Key` 去重,找回也用它)。 */
453
+ readonly requestId: string;
454
+ /** 实际路由到的服务商。 */
455
+ readonly provider: Provider;
456
+ /** 用户配置/工具参数指定的模型(适配器默认值不在其中)。 */
457
+ readonly model: string | undefined;
458
+ /** 传输方式;async 不可用降级时会改为 sync。 */
459
+ transport: ImageTransport;
460
+ status: TransactionStatus;
461
+ /** 物理提交次数(计费风险计数):正常恒为 1,仅同键重提时为 2。 */
462
+ submitAttempts: number;
463
+ /** 凭 requestId 反查原任务的次数(只读查询,不计费)。 */
464
+ recoveryLookups: number;
465
+ /** 服务端任务 ID(提交被接受后可得)。 */
466
+ taskId?: string;
467
+ /** 提交开始/结束时间戳(毫秒)。 */
468
+ submitStartedAt?: number;
469
+ submitFinishedAt?: number;
470
+ /** 服务端幂等回放标记:为 true 时本次没有新建任务。 */
471
+ replayed?: boolean;
472
+ /** 是否发生过降级(async → sync)或同键重提,供结果层透明告知。 */
473
+ degraded?: boolean;
474
+ }
475
+ /** 创建事务账本。 */
476
+ declare function createImageTransaction(input: {
477
+ requestId: string;
478
+ provider: Provider;
479
+ model: string | undefined;
480
+ transport: ImageTransport;
481
+ }): ImageTransaction;
482
+ /** 提交预算上限:默认 1;同键重提策略下允许 2(第二次必须复用同一个幂等键)。 */
483
+ declare function submitBudget(options?: {
484
+ allowSameKeyRetry?: boolean;
485
+ }): number;
486
+ /**
487
+ * 消费一次提交预算。达到上限后再次调用一律抛错——这是「一次请求只生成一张」
488
+ * 的硬闸门:任何异常路径都不可能在同一个事务里再发一次新的计费请求。
489
+ * @throws {GenerationError} 当本事务已用尽提交预算。
490
+ */
491
+ declare function consumeSubmitBudget(tx: ImageTransaction, options?: {
492
+ allowSameKeyRetry?: boolean;
493
+ }): void;
494
+ /**
495
+ * 判定当前失败是否允许回退到**下一个候选服务商**。
496
+ *
497
+ * 与 `isModelNotAcceptedError` 的区别在于多了一层事务状态门:
498
+ * - 状态必须停在 `failed`——即服务端明确表示「没有创建任务」;
499
+ * 状态为 `unknown` 时绝不换家(否则可能两家各生成一张、各扣一次费)。
500
+ * - 提交次数必须恰好为 1(未被同键重提污染)。
501
+ * - 5xx 只有实证的「无可用渠道」形态才允许换家:网关按模型查渠道发生在调用上游
502
+ * 之前,无渠道即无任务;其余 5xx 一律视为未知状态。
503
+ * @param err - 提交抛出的错误。
504
+ * @param tx - 当前事务账本。
505
+ * @returns 是否允许换下一个候选服务商。
506
+ */
507
+ declare function canFallbackToNextProvider(err: unknown, tx: ImageTransaction): boolean;
508
+ /** 结果元数据里的事务摘要(写进工具输出,让用户能核对「提交了几次」)。 */
509
+ interface TransactionReport {
510
+ requestId: string;
511
+ transport: ImageTransport;
512
+ submitAttempts: number;
513
+ recoveryLookups: number;
514
+ status: TransactionStatus;
515
+ taskId?: string;
516
+ replayed?: boolean;
517
+ degraded?: boolean;
518
+ }
519
+ /** 导出事务摘要(缺省字段不出现在结果里,避免噪音)。 */
520
+ declare function reportTransaction(tx: ImageTransaction): TransactionReport;
521
+ /**
522
+ * 构造「提交状态未知」错误。文案必须做到三件事:说清事实(可能已在计费)、
523
+ * 说清客户端已经做了什么(按幂等键查过了、没查到)、给可执行的下一步
524
+ * (凭 requestId 找回,或用户明确要求后重试)。
525
+ */
526
+ declare function unknownStateError(tx: ImageTransaction, cause: unknown): GenerationError;
527
+ /** 找回查询预算(次数与间隔)。 */
528
+ interface RecoveryBudget {
529
+ /** 最多查询次数(含首次)。 */
530
+ attempts: number;
531
+ /** 相邻两次查询之间的等待(毫秒);服务端给了 Retry-After 时首次等待优先用它。 */
532
+ delayMs: number;
533
+ }
534
+ /** 事务执行依赖。 */
535
+ interface RunImageTransactionDeps {
536
+ tx: ImageTransaction;
537
+ adapter: ProviderAdapter;
538
+ params: ImageGenParams;
539
+ /** 提交与查询共用的 HTTP 选项(提交路径内部强制 retryTimes: 0)。 */
540
+ httpOpts: HttpOpts;
541
+ /** 提交后的轮询实现(由工具层注入 TaskManager,本模块不关心轮询细节)。 */
542
+ poll: (taskId: string, signal?: AbortSignal) => Promise<{
543
+ mediaUrl: string;
544
+ }>;
545
+ /** 未知状态策略。 */
546
+ unknownStatePolicy: UnknownStatePolicy;
547
+ /** 找回查询预算。 */
548
+ recovery: RecoveryBudget;
549
+ /** 可注入的等待实现(测试用假时钟)。 */
550
+ sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;
551
+ /** 过程日志(由工具层转成 notes,透明告知用户为什么走了这条路)。 */
552
+ onNote?: (note: string) => void;
553
+ }
554
+ /** 事务结果。 */
555
+ interface RunImageTransactionResult {
556
+ submit: SubmitResult;
557
+ transport: ImageTransport;
558
+ }
559
+ /**
560
+ * 执行图片生成事务:**最多一次提交**,提交后轮询结果;提交结果未知时凭幂等键
561
+ * 找回原任务,而不是重新生成。
562
+ *
563
+ * 分支与依据(服务端 HTTP 契约表):
564
+ * - 202 接受 → 轮询 `task_id`;`X-Idempotency-Replayed` 为真表示本次未新建任务。
565
+ * - 409 `IDEMPOTENCY_IN_PROGRESS` → 任务已存在 → 按 Retry-After 等一下再反查。
566
+ * - 409 `IDEMPOTENCY_KEY_CONFLICT` → 幂等键被复用于不同请求体(客户端 bug)→ 响亮失败。
567
+ * - 404 异步端点不可用 → 抛 {@link AsyncTransportUnavailableError},由调用方降级同步
568
+ * (服务端在创建任务前返回,降级不会重复生成)。
569
+ * - 4xx 其他(400/401/403/413/429)→ 明确没建任务 → 状态置 `failed`,允许换候选。
570
+ * - 超时 / 断连 / 5xx → 状态置 `unknown` → 反查;查到就继续等,查不到按策略处理。
571
+ *
572
+ * @returns 提交结果与最终使用的传输方式。
573
+ * @throws {AsyncTransportUnavailableError} 异步端点在本环境不可用(请降级同步)。
574
+ * @throws {GenerationError} 其他分类错误;`tx.status` 反映是否允许换候选。
575
+ */
576
+ declare function runImageTransaction(deps: RunImageTransactionDeps): Promise<RunImageTransactionResult>;
577
+ /** 异步图片传输在本环境不可用(功能未开启 / 分组平台不支持):调用方应降级同步。 */
578
+ declare class AsyncTransportUnavailableError extends GenerationError {
579
+ constructor(detail: string);
580
+ }
581
+ /** 异步端点不可用的错误码(工具层据此决定降级)。 */
582
+
583
+ /** 传输能力探测缓存:避免每次调用都为一个已知不可用的端点付一次 404 往返。 */
584
+ interface TransportProbeCache {
585
+ /** 已知不可用状态持续到该时间点(毫秒时间戳)。 */
586
+ unavailableUntil: number;
587
+ }
588
+ /** 传输能力探测缓存有效期:服务端上线/开启对象存储后自动恢复,无需重启客户端。 */
589
+ declare const TRANSPORT_PROBE_TTL_MS: number;
590
+ /** 默认找回预算:5 次、间隔 5 秒(服务端提交响应通常秒级落库)。 */
591
+ declare const DEFAULT_RECOVERY_BUDGET: RecoveryBudget;
592
+ /**
593
+ * 依据配置与探测缓存决定本次调用的传输方式。
594
+ * - `sync`:强制同步(无幂等,仅单次提交保障)。
595
+ * - `async`:强制异步;端点不可用时响亮失败(上线验收用这个口径)。
596
+ * - `auto`:优先异步,服务商不支持或近期探测到不可用时降级同步。
597
+ */
598
+ declare function resolveImageTransport(configured: 'async' | 'sync' | 'auto', adapter: ProviderAdapter, probe: TransportProbeCache | undefined, now?: number): ImageTransport;
599
+ //#endregion
600
+ //#region src/image-preflight.d.ts
601
+ /** 预检查输入:本次调用已经解析完的所有决策。 */
602
+ interface ImagePreflightInput {
603
+ provider: Provider;
604
+ /** 工具参数 > 配置 defaultImageModel;undefined 表示交给服务商内置默认。 */
605
+ model: string | undefined;
606
+ /** 请求尺寸(可能是 宽*高 / 宽x高 / 比例)。 */
607
+ size: string;
608
+ /** 是否带参考图(决定文生图 / 图生图)。 */
609
+ hasReferenceImage: boolean;
610
+ /** 本次实际使用的传输方式。 */
611
+ transport: ImageTransport;
612
+ /** 适配器是否声明了异步图片网关能力。 */
613
+ adapterSupportsAsync: boolean;
614
+ config: Config;
615
+ }
616
+ /** 预检查结论:本次调用的完整决策快照,同时作为 notes 透明告知用户。 */
617
+ interface ImagePreflight {
618
+ provider: Provider;
619
+ model: string | undefined;
620
+ size: string;
621
+ mode: 'text-to-image' | 'image-to-image';
622
+ transport: ImageTransport;
623
+ /** 水印后处理决策(未开启时 enabled=false)。 */
624
+ watermark: {
625
+ enabled: boolean;
626
+ text: string;
627
+ };
628
+ }
629
+ /**
630
+ * 执行调用前预检查。任何**确定无法成功**的输入在这里直接失败,绝不带着错误
631
+ * 参数去打一次真金白银的生成请求。
632
+ * @param input - 已解析的调用决策。
633
+ * @returns 预检查结论。
634
+ * @throws {GenerationError} 尺寸写法无法识别、模型明显是视频模型、异步传输不被支持。
635
+ */
636
+ declare function resolveImagePreflight(input: ImagePreflightInput): ImagePreflight;
637
+ /**
638
+ * 模型名是否明显属于视频模型。命中条件之一即可,且**显式配置优先**:
639
+ * 当用户把 defaultImageModel 明确设成该名字时不再拦截(用户的显式选择胜过启发式)。
640
+ * @param model - 模型名。
641
+ * @param config - 插件配置。
642
+ * @returns 是否判定为视频模型。
643
+ */
644
+ declare function looksLikeVideoModel(model: string, config: Config): boolean;
645
+ /**
646
+ * 把预检查结论格式化为一行透明告知,写进工具结果 notes:
647
+ * 「本次用了谁、什么模型、什么尺寸、走哪条传输、要不要打水印」一句话说完,
648
+ * 用户不必查配置或翻服务商后台。
649
+ */
650
+ declare function formatPreflightNote(preflight: ImagePreflight): string;
651
+ //#endregion
652
+ //#region src/providers/wanx.d.ts
653
+ /** 万象适配器实例。 */
654
+ declare const wanxAdapter: ProviderAdapter;
655
+ /** 从配置解析万象 HttpOpts(已由 config.resolveActiveProvider 解析凭证)。 */
656
+ //#endregion
657
+ //#region src/providers/seedance.d.ts
658
+ /** Seedance 适配器实例。 */
659
+ declare const seedanceAdapter: ProviderAdapter;
660
+ /** 复用 downloadMedia。 */
661
+
662
+ //#endregion
663
+ //#region src/providers/threerouter.d.ts
664
+ /** Threerouter 适配器实例:统一入口同时支持文生图与文生视频。 */
665
+ declare const threerouterAdapter: ProviderAdapter;
666
+ /** 复用 downloadMedia。 */
667
+
668
+ //#endregion
669
+ //#region src/media-route.d.ts
670
+ /** webServer 服务的本地结构视图(上游 WebServer 的最小消费子集)。 */
671
+ interface MediaWebServer {
672
+ /** 监听地址:'127.0.0.1' 或 '0.0.0.0'。 */
673
+ host: string;
674
+ /** 注册命名路由,返回注销函数;重复 (kind, path) 抛错。 */
675
+ register(route: {
676
+ kind: 'exact' | 'prefix';
677
+ path: string;
678
+ handler: (req: IncomingMessage, res: ServerResponse) => void | Promise<void>;
679
+ }): () => void;
680
+ }
681
+ /** outputs 媒体路由前缀(prefix 匹配 /outputs 与 /outputs/<文件名>)。 */
682
+ //#endregion
683
+ //#region src/runtime-defaults.d.ts
684
+ /**
685
+ * 运行时覆盖值集合。字段语义与 generate_image / generate_video 工具的
686
+ * 服务商/参数选择一一对应:`undefined` = 未覆盖,工具回落 settings(config)持久值。
687
+ * `imageSize` 为映射后的尺寸串(如 '1024*1024'),`videoAspectRatio` 为比例串
688
+ * (如 '16:9'),`imageStyle` 为风格 id(见 {@link IMAGE_STYLE_OPTIONS})。
689
+ */
690
+ interface RuntimeDefaults {
691
+ /** 图片服务商覆盖('threerouter' | 'wanx' | 'seedance',minimax 无图片能力);undefined 跟随 settings。 */
692
+ imageProvider?: Provider;
693
+ /** 图片尺寸覆盖('宽*高');undefined 跟随 settings。 */
694
+ imageSize?: string;
695
+ /** 图片风格 id 覆盖;undefined 跟随 settings(不拼接风格后缀)。 */
696
+ imageStyle?: string;
697
+ /** 视频服务商覆盖;undefined 跟随 settings。 */
698
+ videoProvider?: Provider;
699
+ /** 视频宽高比覆盖(如 '16:9');undefined 跟随 settings。 */
700
+ videoAspectRatio?: string;
701
+ /** 视频时长覆盖(秒,1-10);undefined 跟随 settings。 */
702
+ videoDuration?: number;
703
+ }
704
+ /** POST /image-video/defaults 接受的单字段写入:null 清除覆盖,否则为合法值。 */
705
+ type RuntimeDefaultsPatch = { [K in keyof RuntimeDefaults]: RuntimeDefaults[K] | null };
706
+ /** 内存态运行时默认值存储。 */
707
+ interface RuntimeDefaultsStore {
708
+ /** 当前覆盖值快照(只读视图;未覆盖字段不出现在对象上)。 */
709
+ get(): Readonly<RuntimeDefaults>;
710
+ /** 合并写入:null 删除该字段覆盖,其余覆盖写入;返回新快照。 */
711
+ patch(patch: RuntimeDefaultsPatch): Readonly<RuntimeDefaults>;
712
+ /** 清空全部覆盖(插件卸载语义;路由层暂不暴露)。 */
713
+ reset(): void;
714
+ }
715
+ /** 创建内存态运行时默认值存储。 */
716
+ declare function createRuntimeDefaultsStore(): RuntimeDefaultsStore;
717
+ /** 图片风格选项:id 即协议值,label 供下拉 UI 展示;'' = 自动(不拼接后缀)。 */
718
+ declare const IMAGE_STYLE_OPTIONS: ReadonlyArray<{
719
+ id: string;
720
+ label: string;
721
+ }>;
722
+ /**
723
+ * 把风格 id 拼接为英文提示词后缀(生成服务端通用做法:对所有 provider 生效)。
724
+ * @param prompt - 原始提示词。
725
+ * @param style - 风格 id;undefined / '' / 白名单外一律原样返回。
726
+ * @returns 实际发给服务商的提示词。
727
+ */
728
+ declare function applyImageStyle(prompt: string, style: string | undefined): string;
729
+ /** 图片尺寸白名单('宽*高');'' 由协议层表示「自动(清除覆盖)」,不在表内。 */
730
+ declare const IMAGE_SIZE_OPTIONS: ReadonlyArray<{
731
+ id: string;
732
+ label: string;
733
+ size: string;
734
+ }>;
735
+ /**
736
+ * 模型家族规则:按厂商关键词对显式 model 参数做小写包含匹配,得到该模型的家族
737
+ * 候选服务商。维护点按「厂商」而非「模型 id」——新模型(wan3.0、qwen-video、
738
+ * minimax 新版本等)自动命中家族规则,无需逐个登记。
739
+ *
740
+ * 家族事实(2026-09):threerouter 是聚合器,出所有家族的模型(wan/minimax/seedance
741
+ * 及文本/图片模型);wanx(阿里百炼)、minimax(官方平台,仅视频)、seedance(火山方舟)
742
+ * 是家族直连商。规则数组顺序即匹配优先级(更具体的家族在前)。
743
+ */
744
+
745
+ /** defaults 路由路径(exact 匹配;桌面渲染进程同源调用)。 */
746
+ declare const DEFAULTS_ROUTE_PATH = "/image-video/defaults";
747
+ /** GET / POST 响应体:六字段齐全,null = 无运行时覆盖且无 settings 持久默认(工具用内置默认)。 */
748
+ type RuntimeDefaultsView = RuntimeDefaultsPatch;
749
+ /**
750
+ * settings 持久默认值视图:{@link extractPersistedDefaults} 从 config 提取出的
751
+ * 合法默认值子集,未提取的字段不出现在对象上(undefined → 合并时跳过)。
752
+ */
753
+ type PersistedDefaultsView = Partial<RuntimeDefaults>;
754
+ /**
755
+ * 从插件持久 config 提取 settings 默认值,作为 defaults 路由合并视图的回落层。
756
+ * 白名单/范围守卫:服务商须命中 PROVIDERS 白名单(空串 = 跟随激活服务商,不
757
+ * 提取)、imageSize 须命中 IMAGE_SIZE_OPTIONS 白名单、videoDuration 须 1-10 整数;
758
+ * settings 手填的遗留越界值一律忽略(composer 显示「自动」,工具用内置默认),
759
+ * 避免把非法持久值经合并视图当作生效值回显。
760
+ * @param config - 已由 Schemastery 填充默认值的插件配置。
761
+ */
762
+ declare function extractPersistedDefaults(config: Config): PersistedDefaultsView;
763
+ /**
764
+ * 校验并归一化 POST body 为存储 patch。严格协议:仅接受六个已知键;
765
+ * null 清除覆盖;'' 表示「自动」(归一化为 null);其余值按字段白名单/范围校验。
766
+ * @param body - 已 JSON.parse 的请求体(可能是任意值)。
767
+ * @returns 归一化后的 patch;校验失败返回错误信息(字符串)。
768
+ */
769
+ declare function parseDefaultsPatch(body: unknown): {
770
+ ok: true;
771
+ patch: RuntimeDefaultsPatch;
772
+ } | {
773
+ ok: false;
774
+ error: string;
775
+ };
776
+ /**
777
+ * 创建 defaults 路由 handler。GET 返回「运行时覆盖 ?? settings 持久默认」合并
778
+ * 视图;POST 校验写入并返回合并视图;非 GET/POST 405;请求体不可解析或校验
779
+ * 失败 400。
780
+ * @param store - 运行时默认值存储。
781
+ * @param persisted - settings 持久默认回落层({@link extractPersistedDefaults}
782
+ * 提取;未提供时用空对象,即不回落)。
783
+ */
784
+ declare function createDefaultsRouteHandler(store: RuntimeDefaultsStore, persisted?: PersistedDefaultsView): (req: node_http0.IncomingMessage, res: node_http0.ServerResponse) => Promise<void>;
785
+ /**
786
+ * 把 defaults 路由注册进 webServer。仅回环地址注册:host 非 127.0.0.1 时返回
787
+ * undefined 且不注册——运行时覆盖值属本机会话状态,不暴露到局域网。
788
+ * @param webServer - webServer 服务实例(结构类型,见 media-route.ts)。
789
+ * @param store - 运行时默认值存储。
790
+ * @param persisted - settings 持久默认回落层(同 {@link createDefaultsRouteHandler})。
791
+ * @returns 路由注销函数;未注册返回 undefined。
792
+ */
793
+ declare function registerDefaultsRoute(webServer: MediaWebServer, store: RuntimeDefaultsStore, persisted?: PersistedDefaultsView): (() => void) | undefined;
794
+ //#endregion
795
+ //#region src/tools/generate-image.d.ts
796
+ /**
797
+ * 工具依赖:配置、任务管理器、attachment 服务实例。
798
+ * `attachments` 由 `apply()` 通过 `ctx.inject(['attachments'], cb)` 在注册时注入,
799
+ * 不在执行体内部运行时 `ctx.get` 读取——依赖关系在构造时即明确。
800
+ */
801
+ interface GenerateImageDeps {
802
+ config: Config;
803
+ taskManager: TaskManager;
804
+ attachments: AttachmentStore;
805
+ ctx: Context;
806
+ /** 运行时默认值存储:composer 热更新覆盖值优先于 settings 持久值。 */
807
+ runtimeDefaults: RuntimeDefaultsStore;
808
+ /** 已解析为绝对路径的 outputsDir(插件唯一解析点,见 index.apply)。 */
809
+ outputsDir: string;
810
+ }
811
+ /**
812
+ * 创建 generate_image 工具定义。
813
+ * 工具参数:prompt(必填,找回模式除外)、image(单图)、images(多参考图)、size、model、recoverRequestId。
814
+ */
815
+ declare function createGenerateImageTool(deps: GenerateImageDeps): _deepseek_ai_dsh_tools0.ToolDefinition;
816
+ //#endregion
817
+ //#region src/tools/generate-video.d.ts
818
+ /** 工具依赖。 */
819
+ interface GenerateVideoDeps {
820
+ config: Config;
821
+ taskManager: TaskManager;
822
+ /** 运行时默认值存储:composer 热更新覆盖值优先于 settings 持久值。 */
823
+ runtimeDefaults: RuntimeDefaultsStore;
824
+ /**
825
+ * 已解析为绝对路径的 outputsDir(插件唯一解析点,见 index.apply)。
826
+ * 与图片链路共用同一个目录,杜绝旁路产物;缺省时回退 config.outputsDir。
827
+ */
828
+ outputsDir?: string;
829
+ }
830
+ /**
831
+ * 创建 generate_video 工具定义。
832
+ * 工具参数:prompt(必填)、duration(可选,1-10秒)、model(可选)、aspectRatio(可选)、
833
+ * image(可选首帧图片,传了即图生视频)、resolution(可选分辨率档位)。
834
+ */
835
+ declare function createGenerateVideoTool(deps: GenerateVideoDeps): _deepseek_ai_dsh_tools0.ToolDefinition;
836
+ //#endregion
837
+ //#region src/index.d.ts
838
+ /** Cordis 插件名,用于 loader 诊断。 */
839
+ declare const name = "image-video";
840
+ /**
841
+ * 必需服务依赖:`tools`(工具注册表)。
842
+ * `attachments` 不在此声明——它由 `generate_image` 通过 `ctx.inject` 按需声明,
843
+ * 缺失时仅 generate_image 不注册,generate_video 与插件本身不受影响。
844
+ */
845
+ declare const inject: string[];
846
+ /**
847
+ * 插件入口:创建任务管理器(注册卸载清理),注册 generate_image / generate_video 工具。
848
+ *
849
+ * `generate_image` 通过 `ctx.inject(['attachments'], cb)` 显式声明对 attachment 服务的依赖:
850
+ * callback 接收已注入 attachments 的子上下文,从中读取服务实例构造时注入工具,
851
+ * 不在执行体内部运行时 `ctx.get` 读取。attachments 服务撤销时,该 fiber dispose,
852
+ * `ctx.tools.register` 的 disposer 自动注销工具。
853
+ *
854
+ * `generate_video` 不依赖 attachments,始终注册。工具注册的 disposer 由 `ctx.tools.register`
855
+ * 内部经 effect 注册,fiber dispose 时自动清理。
856
+ *
857
+ * @param ctx - 插件上下文。
858
+ * @param config - 已由 Schemastery 填充默认值的插件配置。
859
+ */
860
+ declare function apply(ctx: Context, config: Config): void;
861
+ //#endregion
862
+ export { type AsyncImageSubmit, AsyncTransportUnavailableError, Config, type Config as ConfigType, DEFAULTS_ROUTE_PATH, DEFAULT_RECOVERY_BUDGET, type ErrorKind, GenerationError, IMAGE_SIZE_OPTIONS, IMAGE_STYLE_OPTIONS, type ImageAsyncCapability, type ImageGenParams, type ImagePreflight, type ImageTransaction, type ImageTransport, type PersistedDefaultsView, type Provider, type ProviderAdapter, type ProviderCredentials, type RecoveryBudget, type RequestOptions, type RequestResult, type RuntimeDefaults, type RuntimeDefaultsPatch, type RuntimeDefaultsStore, type RuntimeDefaultsView, type SubmitResult, TRANSPORT_PROBE_TTL_MS, TaskManager, type TaskQueryFn, type TaskQueryResult, type TransactionReport, type TransactionStatus, type TransportProbeCache, type UnknownStatePolicy, type VideoGenParams, type WatermarkConfig, type WatermarkPosition, type WatermarkResult, apply, applyImageStyle, applyImageWatermark, buildWatermarkSvg, canFallbackToNextProvider, consumeSubmitBudget, createDefaultsRouteHandler, createGenerateImageTool, createGenerateVideoTool, createImageTransaction, createRuntimeDefaultsStore, extractPersistedDefaults, fitFontSize, formatPreflightNote, inject, isAsyncImageUnavailableError, isModelNotAcceptedError, isUnknownSubmitStateError, looksLikeVideoModel, name, parseDefaultsPatch, registerDefaultsRoute, reportTransaction, resolveImagePreflight, resolveImageTransport, runImageTransaction, seedanceAdapter, submitBudget, threerouterAdapter, unknownStateError, wanxAdapter };