@eddyskywalker/dsh-chatgpt-subscription 0.30.0 → 0.32.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.
Files changed (110) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +64 -1
  3. package/lib/client.js +34034 -2768
  4. package/lib/client.js.map +1 -1
  5. package/lib/index.js +33214 -24259
  6. package/lib/types/client/cline-pass/ClinePassComposerQuota.d.ts +20 -0
  7. package/lib/types/client/cline-pass/ClinePassComposerQuota.d.ts.map +1 -0
  8. package/lib/types/client/cline-pass/ClinePassSection.d.ts +17 -0
  9. package/lib/types/client/cline-pass/ClinePassSection.d.ts.map +1 -0
  10. package/lib/types/client/cline-pass/api.d.ts +84 -0
  11. package/lib/types/client/cline-pass/api.d.ts.map +1 -0
  12. package/lib/types/client/cline-pass/locales.d.ts +1025 -0
  13. package/lib/types/client/cline-pass/locales.d.ts.map +1 -0
  14. package/lib/types/client/cline-pass/styles.d.ts +7 -0
  15. package/lib/types/client/cline-pass/styles.d.ts.map +1 -0
  16. package/lib/types/client/hub/brand-icons.d.ts +2 -2
  17. package/lib/types/client/hub/brand-icons.d.ts.map +1 -1
  18. package/lib/types/client/hub/providers.d.ts.map +1 -1
  19. package/lib/types/client/index.d.ts +2 -0
  20. package/lib/types/client/index.d.ts.map +1 -1
  21. package/lib/types/client/mermaid/renderer.d.ts +23 -0
  22. package/lib/types/client/mermaid/renderer.d.ts.map +1 -1
  23. package/lib/types/client/minimax-code/MinimaxCodeSection.d.ts.map +1 -1
  24. package/lib/types/client/minimax-code/MinimaxVideoDocumentBody.d.ts +86 -0
  25. package/lib/types/client/minimax-code/MinimaxVideoDocumentBody.d.ts.map +1 -0
  26. package/lib/types/client/minimax-code/MinimaxVideoToolView.d.ts +83 -0
  27. package/lib/types/client/minimax-code/MinimaxVideoToolView.d.ts.map +1 -0
  28. package/lib/types/client/minimax-code/VideoFormDialog.d.ts +90 -0
  29. package/lib/types/client/minimax-code/VideoFormDialog.d.ts.map +1 -0
  30. package/lib/types/client/minimax-code/VideoSettingsSections.d.ts +73 -0
  31. package/lib/types/client/minimax-code/VideoSettingsSections.d.ts.map +1 -0
  32. package/lib/types/client/minimax-code/commands-contract.d.ts +35 -0
  33. package/lib/types/client/minimax-code/commands-contract.d.ts.map +1 -0
  34. package/lib/types/client/minimax-code/document-preview.d.ts +45 -0
  35. package/lib/types/client/minimax-code/document-preview.d.ts.map +1 -0
  36. package/lib/types/client/minimax-code/locales.d.ts +206 -2
  37. package/lib/types/client/minimax-code/locales.d.ts.map +1 -1
  38. package/lib/types/client/minimax-code/styles.d.ts.map +1 -1
  39. package/lib/types/client/minimax-code/video-command-host.d.ts +61 -0
  40. package/lib/types/client/minimax-code/video-command-host.d.ts.map +1 -0
  41. package/lib/types/client/minimax-code/video-command.d.ts +126 -0
  42. package/lib/types/client/minimax-code/video-command.d.ts.map +1 -0
  43. package/lib/types/client/minimax-code/video-contract.d.ts +208 -0
  44. package/lib/types/client/minimax-code/video-contract.d.ts.map +1 -0
  45. package/lib/types/client/minimax-code/video-defaults-store.d.ts +61 -0
  46. package/lib/types/client/minimax-code/video-defaults-store.d.ts.map +1 -0
  47. package/lib/types/client/minimax-code/video-form-rules.d.ts +288 -0
  48. package/lib/types/client/minimax-code/video-form-rules.d.ts.map +1 -0
  49. package/lib/types/client/minimax-code/video-media.d.ts +61 -0
  50. package/lib/types/client/minimax-code/video-media.d.ts.map +1 -0
  51. package/lib/types/client/minimax-code/video-slots.d.ts +140 -0
  52. package/lib/types/client/minimax-code/video-slots.d.ts.map +1 -0
  53. package/lib/types/client/progress-updates/markdown-lite.d.ts +19 -6
  54. package/lib/types/client/progress-updates/markdown-lite.d.ts.map +1 -1
  55. package/lib/types/host/antigravity/adapter.d.ts.map +1 -1
  56. package/lib/types/host/cline-pass/account-pool.d.ts +63 -0
  57. package/lib/types/host/cline-pass/account-pool.d.ts.map +1 -0
  58. package/lib/types/host/cline-pass/adapter.d.ts +49 -0
  59. package/lib/types/host/cline-pass/adapter.d.ts.map +1 -0
  60. package/lib/types/host/cline-pass/catalog.d.ts +49 -0
  61. package/lib/types/host/cline-pass/catalog.d.ts.map +1 -0
  62. package/lib/types/host/cline-pass/client.d.ts +118 -0
  63. package/lib/types/host/cline-pass/client.d.ts.map +1 -0
  64. package/lib/types/host/cline-pass/engine.d.ts +223 -0
  65. package/lib/types/host/cline-pass/engine.d.ts.map +1 -0
  66. package/lib/types/host/cline-pass/line.d.ts +55 -0
  67. package/lib/types/host/cline-pass/line.d.ts.map +1 -0
  68. package/lib/types/host/cline-pass/mapper.d.ts +112 -0
  69. package/lib/types/host/cline-pass/mapper.d.ts.map +1 -0
  70. package/lib/types/host/cline-pass/oauth.d.ts +134 -0
  71. package/lib/types/host/cline-pass/oauth.d.ts.map +1 -0
  72. package/lib/types/host/cline-pass/protocol.d.ts +186 -0
  73. package/lib/types/host/cline-pass/protocol.d.ts.map +1 -0
  74. package/lib/types/host/cline-pass/routes.d.ts +71 -0
  75. package/lib/types/host/cline-pass/routes.d.ts.map +1 -0
  76. package/lib/types/host/cline-pass/store.d.ts +97 -0
  77. package/lib/types/host/cline-pass/store.d.ts.map +1 -0
  78. package/lib/types/host/cline-pass/token-store.d.ts +168 -0
  79. package/lib/types/host/cline-pass/token-store.d.ts.map +1 -0
  80. package/lib/types/host/cline-pass/tools.d.ts +21 -0
  81. package/lib/types/host/cline-pass/tools.d.ts.map +1 -0
  82. package/lib/types/host/cline-pass/types.d.ts +168 -0
  83. package/lib/types/host/cline-pass/types.d.ts.map +1 -0
  84. package/lib/types/host/common/model-request-control.d.ts +1 -1
  85. package/lib/types/host/common/model-request-control.d.ts.map +1 -1
  86. package/lib/types/host/common/request-diagnostics.d.ts +1 -1
  87. package/lib/types/host/common/request-diagnostics.d.ts.map +1 -1
  88. package/lib/types/host/minimax-code/client.d.ts.map +1 -1
  89. package/lib/types/host/minimax-code/iso-bmff-duration.d.ts +84 -0
  90. package/lib/types/host/minimax-code/iso-bmff-duration.d.ts.map +1 -0
  91. package/lib/types/host/minimax-code/matrix-client.d.ts +168 -0
  92. package/lib/types/host/minimax-code/matrix-client.d.ts.map +1 -0
  93. package/lib/types/host/minimax-code/media-store.d.ts +153 -0
  94. package/lib/types/host/minimax-code/media-store.d.ts.map +1 -0
  95. package/lib/types/host/minimax-code/routes.d.ts.map +1 -1
  96. package/lib/types/host/minimax-code/video-history.d.ts +240 -0
  97. package/lib/types/host/minimax-code/video-history.d.ts.map +1 -0
  98. package/lib/types/host/minimax-code/video-submit-rules.d.ts +40 -0
  99. package/lib/types/host/minimax-code/video-submit-rules.d.ts.map +1 -0
  100. package/lib/types/host/minimax-code/video-tool.d.ts +757 -0
  101. package/lib/types/host/minimax-code/video-tool.d.ts.map +1 -0
  102. package/lib/types/host/progress-updates/index.d.ts +6 -0
  103. package/lib/types/host/progress-updates/index.d.ts.map +1 -1
  104. package/lib/types/host/progress-updates/projection.d.ts +214 -0
  105. package/lib/types/host/progress-updates/projection.d.ts.map +1 -0
  106. package/lib/types/index.d.ts +12 -0
  107. package/lib/types/index.d.ts.map +1 -1
  108. package/lib/types/shared/cline-pass-contracts.d.ts +267 -0
  109. package/lib/types/shared/cline-pass-contracts.d.ts.map +1 -0
  110. package/package.json +14 -4
@@ -0,0 +1,208 @@
1
+ /**
2
+ * MiniMax 视频能力在浏览器半边的共享契约与纯函数。
3
+ *
4
+ * ## 为什么形状要在这里再写一遍
5
+ *
6
+ * host 那一份(`MinimaxVideoPresentationMeta`)住在 `src/host/minimax-code/` 下。
7
+ * 客户端 tsconfig 的 `include` 只覆盖 `src/client/**` 与 `src/shared/**`——
8
+ * 从浏览器半边 import 宿主模块既越界,也会把宿主的 node 依赖拖进浏览器闭包。
9
+ * 两份形状必须逐字一致(字段名、可选性),由
10
+ * `test/minimax-code-video-toolview.test.tsx` 的赋值断言钉住。
11
+ *
12
+ * ## 视频怎么从工作区走到 `<video>`
13
+ *
14
+ * meta 里的 `videoPath` 是**工作区相对路径**,而浏览器只有一个取字节通道:
15
+ * `ctx.remote.workspaceFiles.readBytes(sessionId, path, options, signal)`
16
+ * (宿主侧边栏图像预览走的是同一条,见
17
+ * `ui-sidebar-documentpreview/src/client/rpc.ts` 的 `ReadDocumentBytes`)。
18
+ * 拿到的 `Uint8Array` 包成 Blob,再 `URL.createObjectURL` 交给 `<video>`:
19
+ * 视频不能像图片那样走 `loadImage`(那是附件专用的),也不能直接写文件路径
20
+ * ——浏览器的 `<video src>` 读不到工作区。
21
+ *
22
+ * 对象 URL 是**手动生命周期**:拿到就建、卸载就 `revokeObjectURL`,见两个组件里的
23
+ * `useObjectUrl`。漏掉那一步等于把整段视频留在内存里。
24
+ *
25
+ * @module @eddyskywalker/dsh-chatgpt-subscription/client/minimax-code/video-contract
26
+ */
27
+ import type { RemoteBytes, RemoteResult } from './video-slots.ts';
28
+ /**
29
+ * `minimax_generate_video` 的线上工具名。
30
+ *
31
+ * `tool.call.toolview` 是按这个字符串 keyed 分发的,拼错一个字视图就永远不渲染
32
+ * (槽位不会报错,它只是永远命不中),所以两边共用这一个常量。
33
+ */
34
+ export declare const MINIMAX_VIDEO_TOOL_NAME = "minimax_generate_video";
35
+ /**
36
+ * 工具结果里的结构化事实,由宿主写进 `output.presentationMeta`。
37
+ *
38
+ * `presentationMeta` 会随会话日志持久化(`packages/core/tools/src/presentation.ts`),
39
+ * 落到客户端的 `ToolResultNode.meta`。工具的结构化 `value` **不会**被持久化,
40
+ * 所以客户端只能用这份 meta,不要指望能读到 `value`。
41
+ */
42
+ export interface MinimaxVideoPresentationMeta {
43
+ /** 工作区相对路径(客户端用会话 cwd 解析成绝对路径)。 */
44
+ readonly videoPath: string;
45
+ /** 视频的 MIME 类型,如 `video/mp4`;用于 Blob 的 `type`。 */
46
+ readonly mediaType: string;
47
+ /** 文件字节数;卡片右下角显示的就是它。 */
48
+ readonly bytes: number;
49
+ /** 生成用的模型 id,如 `MiniMax-H3`。 */
50
+ readonly model: string;
51
+ /** 上游报告的时长;缺失时卡片不显示时长,也不显示占位符。 */
52
+ readonly durationSeconds?: number;
53
+ /** 上游任务 id,便于排查与续查。 */
54
+ readonly taskId: string;
55
+ }
56
+ /**
57
+ * 从工具结果的 `meta` 里读出视频事实,读不到就是 `undefined`。
58
+ *
59
+ * `meta` 在类型上是 `unknown`,且它由**另一个运行时**写入——会话日志可能是
60
+ * 旧版本插件写的、可能缺字段、也可能根本不是这个工具的对象。所以这里逐字段
61
+ * 校验,任何一项不合格就整体当作「没有 meta」,由卡片改画占位块,
62
+ * 而不是让一次审计过的 JSON 把整个对话流带崩。
63
+ *
64
+ * @param meta - `ToolResultNode.meta`(通常是 `output.presentationMeta`)。
65
+ * @returns 通过校验的视频事实;不是本工具的 meta 时 undefined。
66
+ */
67
+ export declare function readVideoMeta(meta: unknown): MinimaxVideoPresentationMeta | undefined;
68
+ /**
69
+ * 把工作区相对路径拼成绝对路径。
70
+ *
71
+ * 分隔符**按 posix 拼**,不按宿主平台拼:这段代码跑在浏览器里,而工作区路径
72
+ * 的规范形是 `/` 分隔(宿主的 `parseFileAddress` 也按这个认)。反斜杠进来的
73
+ * 相对路径先归一化,避免拼出 `C:\\ws\\clips\\a.mp4` 这种混合形态。
74
+ *
75
+ * `cwd` 缺省时(宿主从不认识这个会话的工作区)**原样返回相对路径**:它仍然是
76
+ * 这个会话地址空间里的合法路径,`openFile` 与 `readBytes` 都能用;只是别再声称
77
+ * 它是绝对的——调用方要的是「能打开的路径」,不是「看起来像绝对路径的字符串」。
78
+ *
79
+ * @param cwd - 会话工作区根;未提供时按相对路径处理。
80
+ * @param videoPath - meta 里的工作区相对路径。
81
+ * @returns 绝对路径,或 `cwd` 缺省时的相对路径。
82
+ */
83
+ export declare function absoluteVideoPath(cwd: string | undefined, videoPath: string): string;
84
+ /**
85
+ * 取视频字节的通道。
86
+ *
87
+ * 与宿主 `ctx.remote.workspaceFiles.readBytes` 的**远端签名同形**:会话 id 决定
88
+ * 相对路径解析到哪个工作区根。返回裸字节(`WorkspaceFileBytes.data`),
89
+ * 生命周期归调用方。
90
+ *
91
+ * @param sessionId - 会话 id,决定工作区根。
92
+ * @param path - 绝对路径,或相对该会话工作区根的路径。
93
+ * @param signal - 取消信号;组件卸载时触发。
94
+ * @returns 整段文件字节。
95
+ */
96
+ export type ReadVideoBytes = (sessionId: string, path: string, signal?: AbortSignal) => Promise<Uint8Array>;
97
+ /**
98
+ * 一次远端取字节的结果 → 字节。
99
+ *
100
+ * 远端调用**不抛异常**:它把结果装成 `{ ok: true, value }` 或
101
+ * `{ ok: false, error }`(见 `@deepseek-ai/dsh-typert-protocol` 的
102
+ * `RemoteResult`)。所以字节在 `value.data`,而不是结果对象的 `data`——
103
+ * 直接读 `(await call()).data` 拿到的是 `undefined`,界面会把它显示成
104
+ * 「一直在读」。
105
+ *
106
+ * 失败那一支**抛出去**:卡片按 `code` 与 `details.limit` 区分「文件太大」和
107
+ * 「读不到」,那需要一条真正的异常(`RemoteError` 本身就是带这两个字段的
108
+ * `Error`)。
109
+ *
110
+ * **载荷有两代形状**:≤0.1.6 的宿主给 base64 字符串,≥0.1.7 的宿主给
111
+ * `Uint8Array`。两种都认,否则旧世代会拿到一串 base64 而不是字节。
112
+ *
113
+ * @param result - 远端返回的结果。
114
+ * @returns 整段文件字节。
115
+ * @throws 远端声明的失败,或一份「成功却没有字节」的结果。
116
+ */
117
+ export declare function unwrapVideoBytes(result: RemoteResult<{
118
+ readonly data: RemoteBytes;
119
+ }>): Uint8Array;
120
+ /**
121
+ * 宿主的字节载荷 → 浏览器要用的字节。
122
+ *
123
+ * ≥0.1.7 的宿主直接给 `Uint8Array`;≤0.1.6 的宿主给 base64 字符串,
124
+ * 宿主自己的预览也是用 `atob` 解的(`ui-sidebar-documentpreview/src/client/rpc.ts`
125
+ * 的 `documentFileBytes`)。这里照抄同一套判定。
126
+ *
127
+ * @param data - 远端交回的载荷。
128
+ * @returns 整段文件字节。
129
+ * @throws 载荷既不是字节也不是可解的 base64。
130
+ */
131
+ export declare function decodeVideoBytes(data: RemoteBytes): Uint8Array;
132
+ /**
133
+ * 一次取字节失败的原因。
134
+ *
135
+ * 只有两种:宿主明确说「文件超过整文件上限」,以及**其它一切**。别的原因不值得
136
+ * 在视频台上细分——观众能做的事完全一样(这个文件读不出来),而细分会让每个新的
137
+ * 远端码都得回来改一次文案。
138
+ */
139
+ export type VideoReadFailure = 'too-large' | 'unreadable';
140
+ /** 宿主整文件读取上限的失败码(`workspace-files` 的 `readBytes`)。 */
141
+ export declare const WORKSPACE_FILE_TOO_LARGE = "workspace-file/too-large";
142
+ /**
143
+ * 把一次取字节的异常读成「太大」还是「读不到」。
144
+ *
145
+ * 判定**只看错误上的 `code`**,与宿主自己的文档预览同款做法
146
+ * (`ui-sidebar-documentpreview/src/client/failure-line.ts`):远端失败的形状是
147
+ * `{ code, message, details }`,`code` 就是那条稳定的判别字段,不要去解析
148
+ * `message` 里的英文,也不要靠 `instanceof`——跨包、跨 realm 都不成立。
149
+ *
150
+ * 任何拿不到 `code` 的东西(通道根本没装上、浏览器抛的 TypeError、undefined)
151
+ * 一律归入「读不到」:那是默认的那句话,不能因为一个畸形异常就把文案换成
152
+ * 「文件太大」。
153
+ *
154
+ * @param error - `catch` 到的任意值。
155
+ * @returns `'too-large'` 仅当宿主明确报了这个码,否则 `'unreadable'`。
156
+ */
157
+ export declare function videoReadFailureOf(error: unknown): VideoReadFailure;
158
+ /**
159
+ * 从一次 too-large 失败里读出那个上限。
160
+ *
161
+ * 宿主把它放在 `details.limit`(`packages/api/workspace-files/src/index.ts` 的
162
+ * `RemoteError('workspace-file/too-large', …, { path, limit })`)。读不到就不显示
163
+ * 上限——文案里留一个「—」比编一个数字出来好。
164
+ *
165
+ * @param error - `catch` 到的任意值。
166
+ * @returns 上限字节数,或 undefined。
167
+ */
168
+ export declare function videoReadLimitOf(error: unknown): number | undefined;
169
+ /**
170
+ * 字节数转人读的体积。
171
+ *
172
+ * 只有 11px 的位置放它,所以最多三位有效数字:`986 KB`、`12.4 MB`、`1.02 GB`。
173
+ * 单位之间是普通空格,不引小数点前的零。
174
+ * @param bytes - 文件字节数。
175
+ * @returns 形如 `12.4 MB` 的短标签。
176
+ */
177
+ export declare function formatBytes(bytes: number): string;
178
+ /**
179
+ * 「文件太大,读不出来」那一句,带上宿主报的上限。
180
+ *
181
+ * 宿主把 `details.limit` 交给文案(`failureLine` 的
182
+ * `t('error.tooLarge', { limit: humanBytes(failure.details.limit) })`),这里照做,
183
+ * 只是换成本插件自己的 {@link formatBytes}——两边对同一个数字的写法必须与本卡片
184
+ * 右下角那行体积一致。
185
+ *
186
+ * 上限缺失时退回「—」(`formatBytes` 对非数字的既有行为):一句话里少一个数字,
187
+ * 好过为了凑数字去猜一个上限。
188
+ *
189
+ * @param t - 命名空间化的翻译。
190
+ * @param limit - 宿主报的上限字节数;undefined 时按未知处理。
191
+ * @returns 一句占位文案(中文一句、结尾不加句号)。
192
+ */
193
+ export declare function videoTooLargeText(t: (key: 'videoTooLarge') => string, limit: number | undefined): string;
194
+ /**
195
+ * 秒数转 `m:ss` / `h:mm:ss`。
196
+ *
197
+ * 视频时长是元数据,不是大数字:只补零到分钟位,超过一小时才出现小时段。
198
+ * @param seconds - 时长秒数。
199
+ * @returns 形如 `0:07` 或 `1:02:03` 的短标签。
200
+ */
201
+ export declare function formatDuration(seconds: number): string;
202
+ /**
203
+ * 从路径里取文件名,用于侧边栏那一行元数据。
204
+ * @param path - 绝对或相对路径,`/` 与 `\` 都认。
205
+ * @returns 最后一个分隔符之后的部分;没有分隔符时返回原串。
206
+ */
207
+ export declare function fileNameOf(path: string): string;
208
+ //# sourceMappingURL=video-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-contract.d.ts","sourceRoot":"","sources":["../../../../src/client/minimax-code/video-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAEjE;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,2BAA2B,CAAA;AAE/D;;;;;;GAMG;AACH,MAAM,WAAW,4BAA4B;IAC3C,mCAAmC;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,kDAAkD;IAClD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,yBAAyB;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,gCAAgC;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,kCAAkC;IAClC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;IACjC,uBAAuB;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,4BAA4B,GAAG,SAAS,CAqBrF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAQpF;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CAAA;AAE3G;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,CAAC;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC,GAAG,UAAU,CAGjG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,CAW9D;AAED;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,YAAY,CAAA;AAEzD,sDAAsD;AACtD,eAAO,MAAM,wBAAwB,6BAA6B,CAAA;AAElE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAKnE;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAMnE;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAcjD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,MAAM,EACnC,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,MAAM,CAER;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOtD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI/C"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * 「视频默认参数」的浏览器侧存储。
3
+ *
4
+ * ## 为什么存在浏览器里,而不是 `$DSH_HOME/storages`
5
+ *
6
+ * 这份数据是**表单的初始值**,不是凭据、不是配额、也不影响任何一次请求的内容:
7
+ * 用户没打开设置页时它什么也不做,打开 `/video` 时它只决定三个下拉框的起手值。
8
+ * 存到宿主就要新开一条路由、一个新文件和一套平台加密后端,而那条路由的每一个
9
+ * 读者都是同一个浏览器的同一个页面。
10
+ *
11
+ * 对照的是**生成历史**:那个必须落在宿主,因为写它的是宿主(视频工具在生成成功
12
+ * 之后落一行),浏览器根本没有那次事件。默认参数相反,它是纯 UI 偏好。
13
+ *
14
+ * ## 读不到就当没有
15
+ *
16
+ * localStorage 在三种情况下会抛或返回垃圾:隐私模式下禁用、被别的代码写坏、以及
17
+ * 存储配额满。三种都退化成「一份出厂默认」,而不是让设置页打不开——这是整个仓库
18
+ * 对可选依赖的一贯处理(见 `progress-updates/index.ts` 的 `serviceOf`)。
19
+ *
20
+ * @module @eddyskywalker/dsh-chatgpt-subscription/client/minimax-code/video-defaults-store
21
+ */
22
+ import { type VideoDefaults } from './video-form-rules.ts';
23
+ /** localStorage 的键。带命名空间前缀,避免与宿主其它插件的键撞名。 */
24
+ export declare const VIDEO_DEFAULTS_STORAGE_KEY = "dsh-minimax-code.video-defaults";
25
+ /** 最小可用的 storage 形状:测试注入一个假的,不必造整个 window。 */
26
+ export interface KeyValueStorage {
27
+ getItem(key: string): string | null;
28
+ setItem(key: string, value: string): void;
29
+ removeItem(key: string): void;
30
+ }
31
+ /**
32
+ * 取浏览器 localStorage,取不到就是 undefined。
33
+ *
34
+ * 走 `globalThis` 而不是直接写 `localStorage`:这段代码也会在 jsdom 与 SSR 风格的
35
+ * 渲染里跑,那种环境下这个全局可能根本不存在。
36
+ *
37
+ * @returns storage,或 undefined。
38
+ */
39
+ export declare function browserStorage(): KeyValueStorage | undefined;
40
+ /**
41
+ * 读一份默认参数。
42
+ *
43
+ * 任何解析失败都退化成出厂默认,并且**不写回**:一个被写坏的值留在原处,用户下一次
44
+ * 保存就覆盖掉它了,中途重建一份没有意义。
45
+ *
46
+ * @param storage - 存储;缺省取浏览器 localStorage。
47
+ * @returns 自洽的默认参数(见 `normalizeVideoDefaults`)。
48
+ */
49
+ export declare function readVideoDefaults(storage?: KeyValueStorage | undefined): VideoDefaults;
50
+ /**
51
+ * 写一份默认参数。
52
+ *
53
+ * 写入被拒绝(配额满、隐私模式)时**返回 false 而不是抛**:设置页要把这件事显示成
54
+ * 一句提示,而不是让一次点击把整页带崩。
55
+ *
56
+ * @param defaults - 要保存的值。
57
+ * @param storage - 存储;缺省取浏览器 localStorage。
58
+ * @returns 是否真的写进去了。
59
+ */
60
+ export declare function writeVideoDefaults(defaults: VideoDefaults, storage?: KeyValueStorage | undefined): boolean;
61
+ //# sourceMappingURL=video-defaults-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-defaults-store.d.ts","sourceRoot":"","sources":["../../../../src/client/minimax-code/video-defaults-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAA0B,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAElF,6CAA6C;AAC7C,eAAO,MAAM,0BAA0B,oCAAoC,CAAA;AAE3E,8CAA8C;AAC9C,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IACnC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACzC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,IAAI,eAAe,GAAG,SAAS,CAQ5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,eAAe,GAAG,SAA4B,GAAG,aAAa,CASxG;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,aAAa,EACvB,OAAO,GAAE,eAAe,GAAG,SAA4B,GACtD,OAAO,CAQT"}
@@ -0,0 +1,288 @@
1
+ /**
2
+ * MiniMax 视频参数的**浏览器侧规则副本**与表单状态机。
3
+ *
4
+ * ## 为什么这里又抄了一遍宿主那张表
5
+ *
6
+ * 每个模型的合法时长/分辨率、以及比例随首帧/参考媒体被改写的联动,都写在宿主
7
+ * 的 `src/host/minimax-code/video-tool.ts` 里。浏览器半边 **import 不到**它:
8
+ * 客户端 tsconfig 只覆盖 `src/client/**` 与 `src/shared/**`,跨过去会把宿主的
9
+ * node 依赖拖进浏览器闭包(同 `video-contract.ts` 顶部那条注释的理由)。
10
+ *
11
+ * 所以这里是**逐字抄写**,不是重新推导。抄的是那一份**实测**表
12
+ * (`docs/minimax-video-model-rules.md`),不是文档或猜测:
13
+ *
14
+ * | model | duration | resolutions |
15
+ * | -------------------- | ----------------- | ------------ |
16
+ * | `MiniMax-H3` | 4-15 | 768P, 2K |
17
+ * | `MiniMax-H3-Max` | 5-15 | 480P, 768P |
18
+ * | `MiniMax-Hailuo-2.3` | 6 或 10 | 768P, 1080P |
19
+ *
20
+ * 三张表**两两不同,且没有一张等于并集**——2K 只有 H3 有、480P 只有 H3-Max 有、
21
+ * 1080P 只有 Hailuo 有。所以客户端也**不能**用一张并集去校验:那会让 H3-Max 的
22
+ * 用户选到 2K,然后被服务端在计费之后拒掉。
23
+ *
24
+ * `test/minimax-code-video-form-rules.test.ts` 里的一个用例把这三行钉死,改任何
25
+ * 一边而忘了另一边都会红。
26
+ *
27
+ * ## 比例联动为什么必须在表单层就做掉
28
+ *
29
+ * 宿主的 `resolveVideoSubmissionRatio` 是照上游逐分支抄的:
30
+ *
31
+ * ```ts
32
+ * isH3(model)
33
+ * ? hasKeyframes ? 'adaptive'
34
+ * : hasReferences ? (ratio ?? 'adaptive')
35
+ * : (ratio ?? '16:9')
36
+ * : ratio
37
+ * ```
38
+ *
39
+ * 也就是说:**给了首帧,用户选的比例会被无声改写成 `adaptive`**;纯文本又
40
+ * **不允许** `adaptive`(没有可自适应的对象,宿主会直接拒绝)。
41
+ *
42
+ * 让用户先选一个「16:9」再被改写成「adaptive」,是这个入口最不该犯的错——用户
43
+ * 看到的和发出去的不是一个东西。所以这里把「最终比例」直接算出来给用户看,
44
+ * 并且**不给选择**:`resolveVideoRatioChoice` 返回的 `locked` 就是那个意思。
45
+ *
46
+ * @module @eddyskywalker/dsh-chatgpt-subscription/client/minimax-code/video-form-rules
47
+ */
48
+ /** 三个视频模型,顺序与宿主 `MINIMAX_VIDEO_MODELS` 一致。 */
49
+ export declare const MINIMAX_VIDEO_MODELS: readonly ["MiniMax-H3", "MiniMax-H3-Max", "MiniMax-Hailuo-2.3"];
50
+ export type MinimaxVideoModel = (typeof MINIMAX_VIDEO_MODELS)[number];
51
+ /** 没点名时用的模型(宿主 `DEFAULT_MINIMAX_VIDEO_MODEL`)。 */
52
+ export declare const DEFAULT_MINIMAX_VIDEO_MODEL: MinimaxVideoModel;
53
+ /** 服务端认识的每一个比例拼写,顺序照上游。 */
54
+ export declare const MINIMAX_VIDEO_RATIOS: readonly ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16", "adaptive"];
55
+ export type MinimaxVideoRatio = (typeof MINIMAX_VIDEO_RATIOS)[number];
56
+ /** 首帧/末帧在场时宿主**强制**发送的比例。 */
57
+ export declare const MINIMAX_KEYFRAME_RATIO: MinimaxVideoRatio;
58
+ /** 参考媒体在场、用户没选时宿主用的比例。 */
59
+ export declare const MINIMAX_REFERENCE_DEFAULT_RATIO: MinimaxVideoRatio;
60
+ /** 纯文本、用户没选时宿主用的比例。 */
61
+ export declare const MINIMAX_H3_TEXT_DEFAULT_RATIO: MinimaxVideoRatio;
62
+ /** 宿主 `MINIMAX_H3_DEFAULT_RESOLUTION`:H3 家族省略分辨率时实际发的是 2K。 */
63
+ export declare const MINIMAX_H3_DEFAULT_RESOLUTION: "2K";
64
+ export type MinimaxVideoResolution = '480P' | '768P' | '1080P' | '2K';
65
+ /** 参考媒体的数量上限,与宿主 `video-submit-rules.ts` 的常量一致。 */
66
+ export declare const MAX_REFERENCE_IMAGES = 9;
67
+ export declare const MAX_REFERENCE_VIDEOS = 3;
68
+ export declare const MAX_REFERENCE_AUDIOS = 3;
69
+ export declare const MAX_REFERENCE_MEDIA_TOTAL = 12;
70
+ /** 一个模型的时长规则:闭区间,或一个封闭取值集。 */
71
+ export type VideoDurationRule = {
72
+ readonly kind: 'range';
73
+ readonly min: number;
74
+ readonly max: number;
75
+ } | {
76
+ readonly kind: 'values';
77
+ readonly values: readonly number[];
78
+ };
79
+ /** 一个模型的实测规则。 */
80
+ export interface VideoModelRule {
81
+ readonly model: MinimaxVideoModel;
82
+ readonly duration: VideoDurationRule;
83
+ readonly resolutions: readonly MinimaxVideoResolution[];
84
+ /** 这个模型是否接受参考图/参考视频/参考音频与末帧(宿主 `minimaxModelSupportsReferenceMedia`)。 */
85
+ readonly supportsReferenceMedia: boolean;
86
+ /** 这个模型是否属于 H3 家族,即比例联动的适用范围(宿主 `isH3VideoModel`)。 */
87
+ readonly isH3Family: boolean;
88
+ }
89
+ /**
90
+ * 实测的每模型规则,逐字抄自宿主 `MINIMAX_VIDEO_MODEL_RULES`。
91
+ *
92
+ * 抄错一个字的表现是「客户端放行 → 服务端计费后拒绝」,所以这里连顺序都不改。
93
+ */
94
+ export declare const VIDEO_MODEL_RULES: readonly VideoModelRule[];
95
+ /** @param model - 模型 id。 @returns 该模型的规则,未知时为 undefined。 */
96
+ export declare function videoModelRule(model: string): VideoModelRule | undefined;
97
+ /**
98
+ * 一个模型可以选的时长,**从短到长、去重后**给选择器用。
99
+ *
100
+ * 区间型的模型给的是 1 秒一档的整数刻度(服务端接受区间内任意整数),取值集型的
101
+ * 模型只有那几个值。两者都返回数组,表单因此不必分支。
102
+ *
103
+ * @param model - 模型 id。
104
+ * @returns 合法时长列表;模型未知时为空。
105
+ */
106
+ export declare function durationChoices(model: string): readonly number[];
107
+ /**
108
+ * 一个模型的默认时长。
109
+ *
110
+ * 区间型的模型取**下界**:那是最便宜的一次生成,也是用户第一次点开表单时最不
111
+ * 容易心疼的值。取值集型的模型取第一个值(Hailuo 的 6)。
112
+ *
113
+ * @param model - 模型 id。
114
+ * @returns 默认时长;模型未知时为 undefined。
115
+ */
116
+ export declare function defaultDuration(model: string): number | undefined;
117
+ /**
118
+ * 一个模型的默认分辨率。
119
+ *
120
+ * 取**该模型自己的**第一项,而不是宿主的 `2K`:2K 是 H3 专属,H3-Max 与 Hailuo
121
+ * 都没有,硬套过去就是一个必被拒绝的默认值。
122
+ *
123
+ * @param model - 模型 id。
124
+ * @returns 默认分辨率;模型未知时为 undefined。
125
+ */
126
+ export declare function defaultResolution(model: string): MinimaxVideoResolution | undefined;
127
+ /** 表单里的媒体路径输入(纯文本,不做文件选择器)。 */
128
+ export interface VideoMediaInput {
129
+ /** 首帧图的路径。 */
130
+ readonly inputImagePath?: string;
131
+ /** 末帧图的路径。 */
132
+ readonly lastFrameImagePath?: string;
133
+ /** 参考图路径,多行。 */
134
+ readonly referenceImagePaths?: readonly string[];
135
+ /** 参考视频路径,多行。 */
136
+ readonly referenceVideoPaths?: readonly string[];
137
+ /** 参考视频各自的时长,与 {@link referenceVideoPaths} 同序。 */
138
+ readonly referenceVideoDurationSeconds?: readonly number[];
139
+ /** 参考音频路径,多行。 */
140
+ readonly referenceAudioPaths?: readonly string[];
141
+ }
142
+ /**
143
+ * 这份媒体输入决定的两件事:有没有首帧、有没有参考媒体。
144
+ *
145
+ * 两个布尔直接对应用户能看见的那句提示,以及比例能不能选。
146
+ *
147
+ * @param media - 表单里的媒体路径。
148
+ * @returns 两个判定。
149
+ */
150
+ export declare function mediaPresence(media: VideoMediaInput): {
151
+ hasKeyframes: boolean;
152
+ hasReferences: boolean;
153
+ };
154
+ /** 比例这一栏该画成什么。 */
155
+ export interface VideoRatioChoice {
156
+ /** 最终会发出去的比例;undefined 表示这一栏**不发** `ratio` 字段。 */
157
+ readonly ratio: MinimaxVideoRatio | undefined;
158
+ /** 用户还能不能自己挑。true 时表单画选择器,false 时只显示结果。 */
159
+ readonly selectable: boolean;
160
+ /** 为什么锁死;可选时 undefined。 */
161
+ readonly lockedReason?: 'keyframes' | 'references' | 'text-only';
162
+ /** 用户可以选的比例(仅 `selectable` 时有意义)。 */
163
+ readonly options: readonly MinimaxVideoRatio[];
164
+ }
165
+ /**
166
+ * 决定比例这一栏的形态,**在表单层就把联动做掉**。
167
+ *
168
+ * 三条规则与宿主 {@link resolveVideoSubmissionRatio} 一一对应,只是把「静默改写」
169
+ * 换成「当场显示」:
170
+ *
171
+ * 1. **有首帧** → 强制 `adaptive`,不给选。用户选了也会被改写,所以干脆不给。
172
+ * 2. **有参考媒体** → 默认 `adaptive`,但**可以改**:上游对这个分支是
173
+ * `ratio ?? 'adaptive'`,用户给了就照发。所以这里列出的每一个拼写都是
174
+ * 真正会发出去的那个。
175
+ * 3. **纯文本** → 默认 `16:9`(H3 家族)或「不发」(Hailuo),**`adaptive` 不可选**
176
+ * ——服务端没有可自适应的对象,选了必被拒。
177
+ *
178
+ * @param input - 模型、用户当前选的比例、媒体在场情况。
179
+ * @returns 这一栏的形态。
180
+ */
181
+ export declare function resolveVideoRatioChoice(input: {
182
+ readonly model: MinimaxVideoModel;
183
+ readonly requested?: MinimaxVideoRatio;
184
+ readonly hasKeyframes: boolean;
185
+ readonly hasReferences: boolean;
186
+ }): VideoRatioChoice;
187
+ /**
188
+ * 把多行文本框切成路径数组。
189
+ *
190
+ * 一行一条,去掉首尾空白,丢掉空行。**不做**通配符展开、不做存在性检查:路径
191
+ * 由宿主在提交时解析,浏览器里没有工作区文件系统。
192
+ *
193
+ * @param text - 多行文本。
194
+ * @returns 路径数组。
195
+ */
196
+ export declare function parsePathLines(text: string): string[];
197
+ /**
198
+ * 表单的一项校验失败。
199
+ *
200
+ * 文案在 locales 里,这里只带**哪一条**坏了和它的参数——错误文案的格式(中文
201
+ * 最多两句、结尾不加句号)留给字典管。
202
+ */
203
+ export interface VideoFormIssue {
204
+ readonly code: 'prompt-empty' | 'reference-unsupported' | 'last-frame-unsupported' | 'too-many-images' | 'too-many-videos' | 'too-many-audios' | 'too-many-total' | 'duration-invalid';
205
+ /** 文案模板需要的参数。 */
206
+ readonly params?: Readonly<Record<string, string | number>>;
207
+ }
208
+ /** 表单的完整输入。 */
209
+ export interface VideoFormValues {
210
+ readonly prompt: string;
211
+ readonly model: MinimaxVideoModel;
212
+ readonly ratio?: MinimaxVideoRatio;
213
+ readonly durationSeconds?: number;
214
+ readonly resolution?: MinimaxVideoResolution;
215
+ readonly watermark?: boolean;
216
+ readonly media: VideoMediaInput;
217
+ }
218
+ /**
219
+ * 校验整个表单。
220
+ *
221
+ * 顺序照着服务端自己的检查顺序(model → duration → resolution → prompt → ratio),
222
+ * 因为报告一条服务端根本不会提的规则,比不报告更糟。
223
+ *
224
+ * **提示词为空是唯一挡住提交的理由**;其余都是本地就拦下的、必然被拒的组合
225
+ * (参考媒体给了 Hailuo、条数超限),拦下来只为省一次计费请求。
226
+ *
227
+ * @param values - 表单值。
228
+ * @returns 问题列表;空数组表示可以提交。
229
+ */
230
+ export declare function validateVideoForm(values: VideoFormValues): readonly VideoFormIssue[];
231
+ /**
232
+ * 表单是否满足**提交**的最低条件。
233
+ *
234
+ * 比 {@link validateVideoForm} 宽:那个列表里除了提示词以外的问题都会在提交时被
235
+ * 服务端拒绝,而这里只回答「按钮能不能亮」。真正挡住生成的是提示词——那一条
236
+ * 是任务书里点名的:**缺提示词时不能提交**。
237
+ *
238
+ * @param values - 表单值。
239
+ * @returns 能否提交。
240
+ */
241
+ export declare function canSubmitVideoForm(values: VideoFormValues): boolean;
242
+ /**
243
+ * 把表单拼成一句**给模型看**的话,填进输入框。
244
+ *
245
+ * ## 为什么是这个形状
246
+ *
247
+ * 工具是模型自主调用的,所以这段文字要同时做到三件事:点名工具、把参数写成模型
248
+ * 抄得下来的形态、说清「只发一次」。用等号写字段是刻意的——模型最容易照抄的就是
249
+ * 这种形如签名的行。
250
+ *
251
+ * 比例**只在真的会发出去时才写**:纯文本 + Hailuo 的最终比例是 undefined(宿主
252
+ * 不发这个字段,服务端用自己的默认),这时候替用户编一个 16:9 就是在描述一次
253
+ * 不会发生的请求。
254
+ *
255
+ * ## 「只发一次」为什么必须写进去
256
+ *
257
+ * 提交是**计费**且**终态**的:重发不是续传,是再买一次生成。宿主自己的守卫也只
258
+ * 在同一 session 同一 turn 内生效(`videoSubmissionKey`),换个 turn 就拦不住了。
259
+ * 把这句话交给模型,是这道防线上客户端能出力的那一半。
260
+ *
261
+ * @param values - 表单值(应已通过 {@link resolveVideoRatioChoice} 归一化)。
262
+ * @returns 填进输入框的整段文本。
263
+ */
264
+ export declare function buildVideoDraftText(values: VideoFormValues): string;
265
+ /**
266
+ * 设置页「默认参数」里存的东西。
267
+ *
268
+ * 与 {@link VideoFormValues} 分开:这是**跨会话**的偏好,没有提示词,也没有媒体
269
+ * 路径(那些是一次生成的事)。
270
+ */
271
+ export interface VideoDefaults {
272
+ readonly model: MinimaxVideoModel;
273
+ readonly ratio?: MinimaxVideoRatio;
274
+ readonly durationSeconds?: number;
275
+ readonly watermark: boolean;
276
+ }
277
+ /**
278
+ * 归一化一份默认参数。
279
+ *
280
+ * 存在的理由是**模型换了而时长没跟着换**:用户把默认模型从 H3 改成 Hailuo,原来
281
+ * 的 8 秒就不合法了。这里当场把它换成新模型的默认值,而不是把非法值一路带到表单
282
+ * 里,再让用户在弹窗里看到一条自己没设过的错误。
283
+ *
284
+ * @param value - 任意解析出来的对象。
285
+ * @returns 一份自洽的默认参数。
286
+ */
287
+ export declare function normalizeVideoDefaults(value: unknown): VideoDefaults;
288
+ //# sourceMappingURL=video-form-rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-form-rules.d.ts","sourceRoot":"","sources":["../../../../src/client/minimax-code/video-form-rules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * 视频字节 → `<video>` 的那一段:对象 URL 的生命周期,以及两个界面共用的
3
+ * 「视频台」外框。
4
+ *
5
+ * ## 为什么对象 URL 必须由这里管
6
+ *
7
+ * `URL.createObjectURL` 生成的地址把整段字节钉在内存里,直到显式
8
+ * `revokeObjectURL`。视频动辄几十 MB,漏一次就是一次长期泄漏;而 `<video>` 一旦
9
+ * 拿到 `src` 又会自己缓存。所以生命周期只写在 `useObjectUrl` 里一处:
10
+ * 字节变了就换新地址并撤旧的,组件卸载就撤当前的。
11
+ *
12
+ * ## 为什么两个界面共用一个外框
13
+ *
14
+ * 对话流卡片只有约 520px 宽,侧边栏是全尺寸,两者尺寸差一倍——但观众看到的应该
15
+ * 是**同一个东西的两个尺寸**,不是两套设计。所以 16:9 的视频台只定义一次
16
+ * (`.dshm-video-stage`),两处都渲染 {@link VideoStage},差别只剩容器的宽度。
17
+ *
18
+ * @module @eddyskywalker/dsh-chatgpt-subscription/client/minimax-code/video-media
19
+ */
20
+ /**
21
+ * 把一段字节变成一个可播放的对象 URL,并在字节变化或组件卸载时撤销它。
22
+ *
23
+ * 失败(浏览器不支持 Blob URL、或构造抛错)时返回 `failed`,由调用方把占位块
24
+ * 的文字换成失败措辞——**不抛异常**:一块视频读不出来,不该把整段对话流带崩。
25
+ *
26
+ * @param data - 视频字节;`undefined` 表示还没拿到。
27
+ * @param mediaType - Blob 的 MIME 类型,如 `video/mp4`。
28
+ * @returns 就绪时的 `url`,或 `failed`,或两者皆无(仍在等字节)。
29
+ */
30
+ export declare function useObjectUrl(data: Uint8Array | undefined, mediaType: string): {
31
+ url: string | null;
32
+ failed: boolean;
33
+ };
34
+ /** 占位态:给一段安静的说明,失败时才换成 danger 色。 */
35
+ export interface VideoStagePlaceholder {
36
+ /** 占位块里的一行字(中文最多两句、结尾不加句号)。 */
37
+ readonly text: string;
38
+ /** `quiet` 走三级墨色,`danger` 只在真的失败时用。 */
39
+ readonly tone: 'quiet' | 'danger';
40
+ }
41
+ /** 两个界面共用的视频台外框。 */
42
+ export interface VideoStageProps {
43
+ /** 就绪时的对象 URL;`null` 表示还在占位。 */
44
+ readonly url: string | null;
45
+ /** 占位时显示什么;就绪时忽略。 */
46
+ readonly placeholder: VideoStagePlaceholder;
47
+ /** `<video>` 的无障碍名。 */
48
+ readonly label: string;
49
+ }
50
+ /**
51
+ * 16:9 的视频台:深色底、发丝线、letterbox。
52
+ *
53
+ * 就绪时是 `<video controls preload="metadata">`(`preload="metadata"` 让浏览器
54
+ * 先拿时长与首帧,而不是立刻开始整段下载);否则是同一个外框的虚线形态,
55
+ * 里面一行 tertiary 说明。**失败时外框不变**——数据仍在屏幕上,只是它读不出来。
56
+ *
57
+ * @param props - 对象 URL、占位文案与无障碍名。
58
+ * @returns 视频台。
59
+ */
60
+ export declare function VideoStage({ url, placeholder, label }: VideoStageProps): React.JSX.Element;
61
+ //# sourceMappingURL=video-media.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-media.d.ts","sourceRoot":"","sources":["../../../../src/client/minimax-code/video-media.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAoBrH;AAED,oCAAoC;AACpC,MAAM,WAAW,qBAAqB;IACpC,+BAA+B;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,uCAAuC;IACvC,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAA;CAClC;AAED,oBAAoB;AACpB,MAAM,WAAW,eAAe;IAC9B,gCAAgC;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,qBAAqB;IACrB,QAAQ,CAAC,WAAW,EAAE,qBAAqB,CAAA;IAC3C,uBAAuB;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,eAAe,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAQ1F"}