@oadank/dsh-input-tools 0.3.10 → 0.3.12

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,38 +1,31 @@
1
- # dsh-input-tools —— 语音能力一体化插件(单包双入口)
1
+ # dsh-input-tools —— DSH Web 多功能增强插件
2
2
 
3
- 一个插件、一个名字 `@oadank/dsh-input-tools`,把 DSH Web 的语音能力全部装进去:
4
- - **host 入口**(`lib/index.js`):语音工具 + TTS 六引擎 + ASR + 音色克隆 + 自动语音回复
5
- - **client 入口**(`lib/client.js`):输入框工具条(图片/录音)+ 语音设置页 + 语音复制按钮
3
+ DSH Web 加全套实用能力:**语音**(录音输入 / 多引擎 TTS / 离线 ASR / 音色克隆 / 语音气泡 / AI 语音回复)、**图片**(文本模型也能发图识图)、**余额显示**。
6
4
 
7
- 插件本体**不修改任何 DSH 源码**,通过 `dsh plugin` 命令安装注册即可用基础语音功能;
8
- 完整语音体验(语音消息气泡 / AI 语音回复条)需配合源码补丁,见文末「语音源码补丁」。
5
+ - **host**(服务端):语音工具 + TTS 六引擎 + ASR + 音色克隆 + 自动语音回复
6
+ - **client**(浏览器):输入框工具条(图片/录音)+ 语音设置页 + 余额显示 + 语音文本复制
9
7
 
10
8
  ## 功能
11
9
 
12
- ### Host(服务端)
13
- - **`send_voice` 工具**:agent 主动向用户发送语音横条(可播放、可回看、手机可播)。
14
- - **自动语音回复**:用户发语音(或明确要求语音)后,turn 结束自动合成口语化语音(不念代码/URL/Markdown,最多前 2 句约 200 字)。
15
- - **TTS 引擎**:
16
- | 引擎 | 说明 |
17
- |---|---|
18
- | `auto` | 按「默认语音引擎」选择,未配置时微软 Edge 免费兜底 |
19
- | `xiaomi` | 小米 MiMo(支持 `(唱歌)` 标签触发行唱) |
20
- | `voicedesign` | 小米音色设计(一句自然语言凭空生成音色) |
21
- | `voiceclone` | 小米音色克隆(参考音频复刻音色,15-60 秒最佳) |
22
- | `edge` | 微软 Edge(免费无 key) |
23
- | `local` | 本地 TTS(HTTP 常驻服务优先,命令兜底) |
24
- | `ali` | 阿里 qwen3-tts |
25
- - **ASR**:service(常驻 HTTP)/ cmd(本地命令行)/ api(在线)三模式,配置见设置页。
26
- - **克隆管理工具 `manage_voice_clone`**:注册/设为默认/列出/删除克隆音色。
27
-
28
- ### Client(浏览器)
29
- - **输入框工具条**:图片(官方 draft 链路)+ 语音录音(秒数/取消)。
30
- - **语音设置页**(设置 → 语音服务):引擎折叠卡片、小米三模型分区、克隆样本管理、ASR 模式、试听(合成/原声)。
31
- - **语音消息复制按钮**:用户/AI 语音条尾部复制转写文本。
10
+ ### 语音
11
+ | 能力 | 说明 |
12
+ |---|---|
13
+ | 录音输入 | 输入框麦克风按钮,录音 → 本地 ASR 识别 → 发送 |
14
+ | TTS 六引擎 | auto / 小米 / 音色设计 / 音色克隆 / Edge(免费) / 本地 / 阿里 |
15
+ | 离线 ASR | 本地 sherpa-onnx 常驻服务(18790)或命令行模式,不依赖云 |
16
+ | 音色克隆 | 参考音频复刻音色,自带示例样本,开箱即用 |
17
+ | AI 语音回复 | 用户语音后 AI 自动用语音回(send_voice 工具) |
18
+ | 语音气泡 | 用户/AI 语音消息可点击播放,尾部复制转写文本 |
19
+
20
+ ### 图片
21
+ - 输入框图片按钮上传 **文本模型也能发图**:图片转本地路径,AI 自动调视觉 MCP 识图后回答
22
+
23
+ ### 余额
24
+ - 直连模型时输入框右侧实时显示余额(¥xx)
32
25
 
33
26
  ### 界面截图
34
27
 
35
- **输入框工具条**(图片 + 录音按钮):
28
+ **输入框工具条**(图片 + 录音 + 余额):
36
29
 
37
30
  ![输入框工具条](assets/screenshots/input-toolbar.png)
38
31
 
@@ -54,139 +47,69 @@
54
47
 
55
48
  ## 安装
56
49
 
57
- > 这是 **dsh 的命令**(不是 `npm i -g`):`dsh plugin` 会把插件装进指定的 profile
58
- > (`~/.dsh/profiles/<name>/node_modules/`),不是装到 npm 全局。
59
- > `~/.dsh` 指 DSH 运行时目录(Windows 为 `C:\Users\<你>\.dsh`)。
60
-
61
- ### 方式一(推荐):dsh plugin 一键安装
50
+ ### 场景一:已有 dsh 运行环境(源码版或 npm 版)
62
51
 
63
52
  ```bash
64
53
  dsh plugin --profile web add @oadank/dsh-input-tools
65
54
  ```
66
55
 
67
- 自动完成:下载 npm 包 → 装入 profile → 注册 `cordis.patch.yml` → 重启 dsh-web 生效。
68
- (补丁脚本 `patches/apply-voice-patch.ps1` 也已随包发布,路径在
69
- `node_modules\@oadank\dsh-input-tools\patches\`。)
56
+ 装进当前 profile(`~/.dsh/profiles/<name>/node_modules/`),重启 dsh 生效。
70
57
 
71
- ### 方式二:手动拷包(离线/开发)
58
+ ### 场景二:从零开始(推荐,一键整合版)
72
59
 
73
- 1. **拷插件包**:把本仓库 `lib/`、`package.json` 拷到
74
- `~/.dsh/profiles/node_modules/@oadank/dsh-input-tools/`
75
- (`@oadank` 目录不存在就创建)
60
+ 整合版 fork 已内置语音改造 + 本插件 + 一键配置脚本:
76
61
 
77
- 2. **注册插件**:编辑 `~/.dsh/profiles/web/cordis.patch.yml`,在 insert 列表加:
78
- ```yaml
79
- - insert:
80
- - id: dsh-input-tools
81
- name: '@oadank/dsh-input-tools'
82
- ```
62
+ ```bash
63
+ git clone https://github.com/oadank/deepseek-harness.git
64
+ cd deepseek-harness
65
+ # Windows:
66
+ powershell -ExecutionPolicy Bypass -File scripts\setup-profile.ps1
67
+ # Linux/macOS:
68
+ bash scripts/setup-profile.sh
69
+ pnpm install
70
+ pnpm run build:web
71
+ dsh --profile web
72
+ ```
83
73
 
84
- 3. **重启 dsh-web 生效**(按你的系统选择一种):
85
- - Windows + nssm 服务:`nssm restart dsh-web`
86
- - Linux + systemd:`systemctl restart dsh-web`
87
- - 手动启动:停掉当前 dsh 进程后重新运行启动命令
74
+ setup 脚本自动完成:装插件进 profile → 注册 → 检查 ffmpeg → 提示可选 ASR。**无需再执行 dsh plugin add**。
88
75
 
89
76
  ### 可选:本地 ASR(离线识别)
90
77
 
91
- - **Windows**:管理员 PowerShell 运行 `scripts/install-asr.ps1`,自动下载
92
- sherpa-onnx + SenseVoice 模型、注册 `asr` 常驻服务(端口 18790,开机自启)。
93
- - **Linux**:手动部署 sherpa-onnx 离线识别服务(监听 127.0.0.1:18790,
94
- 接口 `POST /transcribe {"audioPath":"..."}` / `GET /health`),或使用 ASR 的
95
- cmd/api 模式。
96
-
97
- 设置页 ASR 模式选「本地常驻服务」指向 18790 即可。
98
-
99
- ## 配置
100
-
101
- 所有语音设置保存在 `~/.dsh/voice-config.json`(设置页实时读写,AI 的 `send_voice`
102
- 描述里会注入当前配置摘要,无需翻源码)。默认语音引擎、各引擎音色/Key、克隆样本、
103
- ASR 模式都在设置页「语音服务」分区配置。
78
+ - **Windows**:管理员 PowerShell 运行 `scripts\install-asr.ps1`(插件包内),自动下载 sherpa-onnx + 模型(约 260MB)、注册 `asr` 服务(18790)
79
+ - **Linux**:手动部署 18790 识别服务,或用 ASR cmd/api 模式
104
80
 
105
- ## 依赖
81
+ ### 依赖
106
82
 
107
- - `@deepseek-ai/dsh-tools`(DSH profiles 自带,用于注册工具)
108
- - `ws`(Edge TTS WebSocket;profiles 自带)
109
- - **ffmpeg**(语音转码用,见下)
83
+ - **ffmpeg**(语音转码必需):Windows `winget install ffmpeg`;Linux `sudo apt install ffmpeg`
84
+ - 视觉 MCP(图片识图用):在 dsh 设置里配置 vision MCP 服务(如 visionqa / zai-vision)
110
85
 
111
- ### ffmpeg(必需)
112
-
113
- 语音转码(录音 webm→wav、克隆样本格式转换、ASR 音频预处理)依赖 **ffmpeg**。
114
- 插件按以下顺序自动定位可执行文件:
115
-
116
- 1. 环境变量 `DSH_VOICE_FFMPEG_BIN`(显式指定完整路径)
117
- 2. PATH 探测(`where ffmpeg` / `which ffmpeg`)
118
- 3. 兜底已知安装位置
119
-
120
- **安装**:Windows 执行 `winget install ffmpeg`(装完一般会自动加 PATH);
121
- Linux(Debian/Ubuntu)执行 `sudo apt install ffmpeg`。装好后无需任何配置,插件自动探测;
122
- 若装在特殊位置,设环境变量 `DSH_VOICE_FFMPEG_BIN=/路径/ffmpeg` 即可。
123
-
124
- > 没有 ffmpeg 时:本地 ASR(service/cmd 模式)和克隆样本的非 mp3/wav 格式转换会失败,
125
- > 但小米/edge 在线 TTS 不受影响。
86
+ ## 配置
126
87
 
127
- ## 语音源码补丁(完整体验原生语音消息,可选)
88
+ 语音设置都在设置页「语音服务」分区(引擎、音色、Key、克隆、ASR 模式),存于 `~/.dsh/voice-config.json`。
128
89
 
129
- dsh 的 npm 安装版(0.1.0-rc.7)**契约不支持原生语音消息**(voice content、语音消息气泡、
130
- AI 语音回复条均为本地源码增强,官方源码/官方发布版默认都没有)。要用完整语音体验,
131
- **二选一**:
90
+ ## 语音源码补丁(完整体验原生语音消息)
132
91
 
133
- ### 方案 A:官方源码 + 破解脚本(推荐,来源可信)
92
+ dsh 官方版(npm rc.7 / 官方源码)**契约不支持原生语音消息**(voice 消息气泡、AI 语音回复条)。二选一:
134
93
 
135
- 1. **克隆官方源码**(任意目录,位置不限):
136
- ```bash
137
- git clone https://github.com/deepseek-ai/deepseek-harness.git
138
- cd deepseek-harness
139
- git checkout 141eb6fef8 # 官方 dsh-0.1.0-rc.8 release 合并点
140
- ```
141
- 2. **打语音补丁**(Windows 管理员 PowerShell;脚本自动探测源码位置,
142
- 找不到时会提示你输入源码路径):
143
- ```powershell
144
- # 插件 npm 安装后,补丁在本机位置:
145
- cd node_modules\@oadank\dsh-input-tools\patches
146
- powershell -ExecutionPolicy Bypass -File apply-voice-patch.ps1
147
- ```
148
- 脚本自动:探测/输入源码仓库 → 校验补丁可应用 → 备份未提交改动 → 应用 → 幂等(已打跳过)。
149
- 3. **构建并启动**:
150
- ```bash
151
- pnpm install
152
- pnpm run build:web # 前端语音气泡渲染在此步生效
153
- dsh --profile web # 或注册为系统服务(Windows 可用 nssm)
154
- ```
155
- 4. **安装语音插件**:`dsh plugin --profile web add @oadank/dsh-input-tools`
156
- 5. **可选:本地 ASR**:见上文「可选:本地 ASR」。
94
+ ### 方案 A:官方源码 + 破解脚本
157
95
 
158
- ### 方案 B:直接克隆整合版(插件已内置,一键安装,推荐大多数用户)
96
+ ```bash
97
+ git clone https://github.com/deepseek-ai/deepseek-harness.git
98
+ cd deepseek-harness
99
+ git checkout 141eb6fef8 # 官方 dsh-0.1.0-rc.8 基线
100
+ # 打补丁(脚本自动探测/输入源码位置):
101
+ powershell -ExecutionPolicy Bypass -File <插件目录>\patches\apply-voice-patch.ps1
102
+ pnpm install && pnpm run build:web && dsh --profile web
103
+ ```
159
104
 
160
- 整合版 fork **已内置全部语音改造 + 本语音插件**(`internal-plugins/dsh-input-tools/`),
161
- 还带一键配置脚本(自动把插件注册进 profile、检查 ffmpeg),**clone 即用、零手工配置**:
105
+ ### 方案 B:直接用整合版 fork(推荐)
162
106
 
163
107
  ```bash
164
108
  git clone https://github.com/oadank/deepseek-harness.git
165
109
  cd deepseek-harness
166
- # Windows:
167
110
  powershell -ExecutionPolicy Bypass -File scripts\setup-profile.ps1
168
- # Linux/macOS:
169
- bash scripts/setup-profile.sh
170
- pnpm install
171
- pnpm run build:web
172
- dsh --profile web
111
+ pnpm install && pnpm run build:web && dsh --profile web
173
112
  ```
174
113
 
175
- `setup-profile.ps1/.sh` 自动完成:把内置插件装进
176
- `~/.dsh/profiles/node_modules/@oadank/dsh-input-tools/` 注册 `cordis.patch.yml`
177
- → 检查 ffmpeg → 提示可选 ASR。之后**无需再执行 `dsh plugin add`**。
178
-
179
- - **可选:本地 ASR**:Windows 运行 `internal-plugins\dsh-input-tools\scripts\install-asr.ps1`;
180
- Linux 见上文「可选:本地 ASR」。
181
- - **升级**:`git pull` 后重跑一次 setup 脚本即同步插件。
182
-
183
- ### 说明与限制
184
-
185
- - 补丁/脚本已随 npm 包发布(`patches/` 目录),git 仓库同步维护。
186
- - **补丁基线**:官方 commit `141eb6fef8`(dsh-0.1.0-rc.8 release 合并点)。
187
- 官方后续更新的 master 与本补丁可能不兼容,**请先 `git checkout 141eb6fef8` 再打补丁**;
188
- 若已应用过,重跑脚本会检测到并跳过(幂等)。
189
- 回滚:`git apply -R <patch>` 或 `git checkout -- <文件>`。
190
- - **npm 版(rc.7)说明**:语音输入(录音→ASR→发送)可用;AI 语音可合成(音频生成);
191
- 但语音消息气泡/语音回复条受 rc.7 前端限制无法原生显示(插件 DOM 注入方案受 React
192
- 重渲染影响不稳定,已禁用)。完整体验请使用源码版(方案 A 或 B)。
114
+ > 补丁基线官方 rc.8(141eb6fef8),官方后续更新可能不兼容,请先 checkout 该基线再打。回滚:`git apply -R`。
115
+ > npm 版(rc.7)限制:语音输入/合成可用,但语音气泡/AI 语音回复条无法原生显示(完整体验用源码版)。
package/lib/client.js CHANGED
@@ -32,6 +32,10 @@ window.__ModuleLoader__.load({
32
32
 
33
33
  // ── 附件槽桥:官方 onAddImages 由 attachments 槽组件挂载时存入,left 按钮调用 ──
34
34
  let sharedOnAddImages = null;
35
+ // [2026-08-21] draft 图片共享:attachments 槽挂载时把当前 draft 图(ComposerAttachment[])
36
+ // 与移除回调存入模块级,语音发送时可一起带上、发完清掉(解决"选了图发语音图被留下")。
37
+ let sharedDraftImages = [];
38
+ let sharedRemoveImage = null;
35
39
 
36
40
  // ── [2026-08-21] 语音气泡(聊天界面 DOM 注入,安装即用,不依赖 dsh 源码支持)────
37
41
  // 录音 → 存服务器(/voice/outbox/save)→ ASR 转文本 → 发【用户语音】标记文本;
@@ -158,13 +162,38 @@ window.__ModuleLoader__.load({
158
162
  if (voiceErrorTimerRef.current !== null) window.clearTimeout(voiceErrorTimerRef.current);
159
163
  voiceErrorTimerRef.current = window.setTimeout(() => setVoiceError(null), 6000);
160
164
  };
161
- const sendAsText = async (text) => {
165
+ // [2026-08-21] draft 图片转 image content(File→base64),语音可与图片一起发送
166
+ const draftImageContents = async () => {
167
+ const imgs = Array.isArray(sharedDraftImages) ? sharedDraftImages : [];
168
+ const out = [];
169
+ for (const a of imgs) {
170
+ const file = a?.file;
171
+ if (!file) continue;
172
+ const b64 = await new Promise((resolve) => {
173
+ const r = new FileReader();
174
+ r.onload = () => resolve(String(r.result).split(",")[1] ?? "");
175
+ r.onerror = () => resolve("");
176
+ r.readAsDataURL(file);
177
+ });
178
+ if (b64 !== "") out.push({ type: "image", mediaType: file.type || "image/jpeg", data: b64, name: file.name });
179
+ }
180
+ return out;
181
+ };
182
+ // [2026-08-21] 语音发送成功后清掉 draft 图片(否则图还留在输入框上)
183
+ const clearDraftImages = () => {
184
+ const imgs = Array.isArray(sharedDraftImages) ? sharedDraftImages : [];
185
+ if (typeof sharedRemoveImage === "function") {
186
+ for (const a of imgs) { try { sharedRemoveImage(a.id); } catch { /* ignore */ } }
187
+ }
188
+ sharedDraftImages = [];
189
+ };
190
+ const sendAsText = async (text, images) => {
162
191
  // [2026-08-21] 降级路径:XDN(npm rc.7) 不支持 voice content。带【用户语音】标记让 AI
163
192
  // 知道这是语音转的文本,可以按规则(自动 TTS)回复。
164
193
  const marked = "【用户语音】" + text;
165
194
  const response = await connection.api.sessions.prompt({
166
195
  sessionId, mode: "queue",
167
- content: [{ type: "text", text: marked }],
196
+ content: [{ type: "text", text: marked }, ...images],
168
197
  });
169
198
  const result = response?.result;
170
199
  if (!result || !result.ok) {
@@ -172,25 +201,26 @@ window.__ModuleLoader__.load({
172
201
  ? result.error.message : "语音发送失败,请重试");
173
202
  }
174
203
  };
175
- const sendAsVoice = async () => {
204
+ const sendAsVoice = async (images) => {
176
205
  // 首选:多模态直发(AI 能听原音,消息渲染为语音气泡)——本机 lecoo / dev rc.8 支持
177
206
  const response = await connection.api.sessions.prompt({
178
207
  sessionId, mode: "queue",
179
- content: [{ type: "voice", mediaType, data }],
208
+ content: [{ type: "voice", mediaType, data }, ...images],
180
209
  });
181
210
  return response?.result;
182
211
  };
183
212
  try {
213
+ const images = await draftImageContents();
184
214
  // [2026-08-21 修] 先直发 voice,失败时降级 ASR 转文本(rc.7 兼容)。
185
215
  // 这样本机/rc.8 享受多模态(AI 听到原音 + 语音消息气泡),XDN/rc.7 自动降级不报错。
186
216
  let result;
187
217
  try {
188
- result = await sendAsVoice();
218
+ result = await sendAsVoice(images);
189
219
  } catch (voiceErr) {
190
220
  result = null;
191
221
  }
192
222
  // 直发成功(rc.8/dev):result.ok true
193
- if (result && result.ok) return;
223
+ if (result && result.ok) { clearDraftImages(); return; }
194
224
  // 失败或不支持:尝试降级
195
225
  const errMsg = result?.error?.message ?? "";
196
226
  // 只有"contract/payload"类错误才降级;其他业务错误直接提示
@@ -216,7 +246,8 @@ window.__ModuleLoader__.load({
216
246
  if (!td?.ok) { fail(td?.error ?? "语音识别失败,请检查 ASR 配置"); return; }
217
247
  const text = typeof td?.text === "string" ? td.text.trim() : "";
218
248
  if (text === "") { fail("没听清,请再说一次"); return; }
219
- await sendAsText(text);
249
+ await sendAsText(text, images);
250
+ clearDraftImages();
220
251
  } catch (e) {
221
252
  fail(String(e && typeof e.message === "string" && e.message !== "" ? e.message : e));
222
253
  }
@@ -318,6 +349,12 @@ window.__ModuleLoader__.load({
318
349
  if (typeof onAddImages === "function") sharedOnAddImages = onAddImages;
319
350
  }, [onAddImages]);
320
351
 
352
+ // [2026-08-21] draft 图同步到模块级(语音发送一起带 + 发完清掉)
353
+ useEffect(() => {
354
+ sharedDraftImages = Array.isArray(attachments) ? attachments : [];
355
+ if (typeof onRemoveImage === "function") sharedRemoveImage = onRemoveImage;
356
+ }, [attachments, onRemoveImage]);
357
+
321
358
  useEffect(() => {
322
359
  if (zoom !== null && !items.some((a) => a.id === zoom.id)) setZoom(null);
323
360
  }, [items, zoom]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oadank/dsh-input-tools",
3
- "version": "0.3.10",
3
+ "version": "0.3.12",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -3607,6 +3607,43 @@ index 395e2da55f..d1548d4961 100644
3607
3607
  if (facts.bindHost !== '127.0.0.1') return 'browse'
3608
3608
  if (present(facts.env.SSH_CONNECTION) || present(facts.env.SSH_TTY)) return 'browse'
3609
3609
  if (facts.platform === 'darwin' || facts.platform === 'win32') return 'native'
3610
+ diff --git a/packages/llm/llm-deepseek/src/adapter.ts b/packages/llm/llm-deepseek/src/adapter.ts
3611
+ index 638d555b1e..f93aaa2ed8 100644
3612
+ --- a/packages/llm/llm-deepseek/src/adapter.ts
3613
+ +++ b/packages/llm/llm-deepseek/src/adapter.ts
3614
+ @@ -236,19 +236,20 @@ export class DeepSeekAdapter extends LlmAdapter {
3615
+ let attachments: AttachmentStore | undefined
3616
+ if (hasImages) {
3617
+ const model = connection.models.find(entry => entry.id === options.model)
3618
+ - if (model?.inputModalities?.includes('image') !== true) {
3619
+ - throw new LlmError(
3620
+ - `DeepSeek model "${options.model}" does not accept image input.`,
3621
+ - 'UNSUPPORTED_CONTENT',
3622
+ - )
3623
+ - }
3624
+ - attachments = this.config.resolveAttachments?.()
3625
+ - if (attachments === undefined) {
3626
+ - throw new LlmError(
3627
+ - 'DeepSeek image conversion requires the durable attachment service.',
3628
+ - 'UNSUPPORTED_CONTENT',
3629
+ - )
3630
+ + if (model?.inputModalities?.includes('image') === true) {
3631
+ + // 多模态模型:走附件转换(图片转 base64 附件随请求发送)
3632
+ + attachments = this.config.resolveAttachments?.()
3633
+ + if (attachments === undefined) {
3634
+ + throw new LlmError(
3635
+ + 'DeepSeek image conversion requires the durable attachment service.',
3636
+ + 'UNSUPPORTED_CONTENT',
3637
+ + )
3638
+ + }
3639
+ }
3640
+ + // [本地改造 2026-08-21] 非多模态模型(文本模型)不抛错:
3641
+ + // request() 走 serializeRequest → serializeMessages → imagesAsText,
3642
+ + // 图片块会转成本地路径文本,agent 用视觉 MCP(mcp__visionqa__look 等)识图后再回答,
3643
+ + // 因此 deepseek-v4-flash 等文本模型同样支持发图(不再报 does not accept image input)。
3644
+ }
3645
+ const apiKey = await this.config.resolveApiKey(connection)
3646
+ const userId = this.config.resolveUserId()
3610
3647
  diff --git a/packages/llm/llm-deepseek/src/serialize.ts b/packages/llm/llm-deepseek/src/serialize.ts
3611
3648
  index 498b3fb2f7..a5e8458366 100644
3612
3649
  --- a/packages/llm/llm-deepseek/src/serialize.ts