dsh-sidenote 0.7.2 → 0.7.3

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
@@ -23,9 +23,9 @@
23
23
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-60708E" alt="MIT license"></a>
24
24
  </p>
25
25
 
26
- ![新版浅色界面:左侧保留主对话,右侧深入讨论,结论回到主输入框](docs/assets/workflow.jpg)
26
+ ![划选文字后可添加到对话或在侧边提问;同屏展示侧聊回答、待发送的批注与回流标签,以及已发送消息中的上下文气泡](docs/assets/workflow.jpg)
27
27
 
28
- <p align="center"><sub>dsh-sidenote 0.6.0 · DSH 0.2.0-rc.2 · 原生侧栏 · 浅色主题</sub></p>
28
+ <p align="center"><sub>dsh-sidenote 0.7.2 · DSH 0.2.1-rc.2 · DeepSeek V4.1 Flash · 真实交互录制</sub></p>
29
29
 
30
30
  ## 安装
31
31
 
@@ -51,7 +51,7 @@ dsh plugin --profile web add dsh-sidenote
51
51
 
52
52
  划选主对话或侧聊中的一段回复,写下问题或修改意见。**原文和注释一起保留**,可累积多条,发送前预览、移除,正文草稿照常编辑。
53
53
 
54
- 读到「没有结果时,引导用户调整搜索词」,就选中这一句,追问「这里如何设计才不会让用户卡住?」。
54
+ 读到「提示“未找到”,并给出放宽条件建议」,就选中这一句,追问「给一版可直接使用的空状态」。
55
55
 
56
56
  ### 有结论,带回正在做的事
57
57
 
@@ -61,11 +61,11 @@ dsh plugin --profile web add dsh-sidenote
61
61
 
62
62
  **划选一句 → 带着上下文追问 → 把结论带回主线。**
63
63
 
64
- ![浅色主题操作录屏:划选原文、添加问题、发送到侧边聊天、回流结论](docs/assets/demo.gif)
64
+ ![真实 Flash 演示:划选批注、悬浮查看与编辑、侧聊追问、图标回流,以及发送后的气泡内引用](docs/assets/demo.gif)
65
65
 
66
66
  [观看清晰版 MP4](docs/assets/demo.mp4) · [查看静态截图](docs/assets/workflow.jpg)
67
67
 
68
- <sub>以上素材重新录制于 dsh-sidenote 0.6.0 / DSH 0.2.0-rc.2。使用隔离环境中的示例对话与本地演示模型,展示真实界面操作;内容与回答为合成示例。</sub>
68
+ <sub>2026-10-25 录制于 dsh-sidenote 0.7.2 / DSH 0.2.1-rc.2。以笔记搜索设计为例,真实调用官方 DeepSeek V4.1 Flash 生成回答;约 43 秒的录屏展示实际操作与完整回复过程。<a href="docs/assets/README.md">素材说明</a></sub>
69
69
 
70
70
  ## 用起来顺手的细节
71
71
 
@@ -1,23 +1,38 @@
1
- # README media / 首页素材
1
+ # README and storefront media / 首页与商店素材
2
2
 
3
- The screenshots and recording used by the README were captured on **2026-10-18** with **dsh-sidenote 0.6.0** (source: `7ed85e4`) and **DSH 0.2.0-rc.2**, using the native right sidebar without better-sidebar. The host's active bundle inventory and the mounted plugin's build hash were checked before capture.
3
+ Captured on **2026-10-25** with the published **dsh-sidenote 0.7.2** package (source: `0d55fcd`) and **DSH 0.2.1-rc.2**, using native Conversation and the native right sidebar. The mounted plugin's version and bundle digest, plus the host's active conversation, composer, and sidebar packages, were checked before capture.
4
4
 
5
- 首页截图与录屏于 **2026-10-18** 重新采集,使用 **dsh-sidenote 0.6.0**(源码 `7ed85e4`)与 **DSH 0.2.0-rc.2** 原生右侧栏,不安装 better-sidebar。采集前核对了宿主实际激活的组件版本与插件构建摘要。
5
+ 素材于 **2026-10-25** 重新录制,使用已发布的 **dsh-sidenote 0.7.2**(源码 `0d55fcd`)与 **DSH 0.2.1-rc.2** 原生对话和右侧栏。录制前核对了实际挂载的插件版本与构建摘要,以及宿主正在运行的对话、输入框和侧栏组件版本。
6
6
 
7
- - `workflow.jpg`: the main and side conversations with a returned answer / 主、侧对话与回流结论。
8
- - `selection.jpg`: a selected passage and its note editor / 划选与注释编辑器。
9
- - `sidechat.jpg`: a completed side-chat response / 侧聊问答。
10
- - `demo.gif`, `demo.mp4`: the same continuous selection → annotation → side reply → reflow sequence / 同一段连续操作的 GIF 与 MP4。
11
- - `hero.svg`, `hero-en.svg` and their `-compact.svg` variants: original vector covers; regenerate with `python3 scripts/build-brand-assets.py` / 原创矢量封面,可用该命令重新生成。
7
+ ## Real model responses / 真实模型回答
12
8
 
13
- The host uses its **light theme** and a 16 px conversation font. Screenshots show the real interface; they are not UI mockups. The recording preserves browser frame timing. A browser translation extension's floating control was temporarily hidden during capture and restored afterwards. No DSH controls were altered.
9
+ The example task is designing a note app's search experience. All assistant replies were generated through the official **DeepSeek V4.1 Flash** API at `api.deepseek.com`, using model ID `deepseek-flash` with thinking off. This ID's mapping is documented in the [official model updates](https://api-docs.deepseek.com/updates/). Request metadata confirmed successful, completed responses. No fixed-answer adapter or prewritten assistant messages were used.
14
10
 
15
- 宿主使用**浅色主题**与 16 px 会话字号。截图来自真实界面,录屏保留浏览器帧的时间间隔。录制期间临时隐藏了浏览器翻译扩展的浮动控件,随后恢复;没有修改 DSH 控件。
11
+ 演示任务是设计笔记应用的搜索体验。全部助手回复都实际调用 `api.deepseek.com` 的 **DeepSeek V4.1 Flash** 生成,模型 ID 为 `deepseek-flash`,关闭思考模式;该 ID 的对应关系见[官方更新说明](https://api-docs.deepseek.com/updates/)。请求元数据确认调用成功并完成,没有使用固定回答的适配器或预先写入的助手消息。
16
12
 
17
- Conversation content is a synthetic note-search design example. A local demo adapter supplies fixed answers through the host's LLM interface; the fork, annotation, submission, and reflow paths are real. This illustrates the workflow, not model answer quality or latency. No private sessions or external model credentials are used.
13
+ The recording starts with the real main-chat answer already visible. It then shows selection and annotation, a real side-chat response, hover previews, editing a pending note, the clear button's reveal, the reply-toolbar handback action, sending the main draft with both kinds of context, and inspecting the sent message. The main model's final answer incorporates the returned empty-state copy and the edited annotation.
18
14
 
19
- 对话内容是合成的笔记搜索设计示例。本地演示模型通过宿主 LLM 接口提供固定回答;fork、注释、发送与回流均执行真实流程。素材用于说明操作,不代表模型回答质量或响应速度,也不使用私人会话或外部模型凭证。
15
+ 录屏从已经生成的主线回答开始,随后展示划选与批注、真实侧聊回答、悬浮预览、原位编辑、清除按钮显现、回复操作栏回流、携带两类上下文发送,以及发送后的气泡详情。主线最后的真实回答同时采纳了带回的空状态文案与修改后的批注。
20
16
 
21
- For future captures, use a fresh isolated DSH home and a verified host version, confirm the mounted bundle, select the light theme, and repeat the complete workflow. The older `capture-demo.mjs` and `capture-video.mjs` scripts target historical BS layouts and do not reproduce these native-sidebar assets unchanged.
17
+ ## Assets / 文件
22
18
 
23
- 以后重录时,使用全新隔离的 DSH home 和已验证宿主版本,核对实际挂载构建,选择浅色主题,并走完完整流程。旧 `capture-demo.mjs`、`capture-video.mjs` 面向历史 BS 布局,不能原样用于复现这组原生侧栏素材。
19
+ - `workflow.jpg`: a follow-up capture showing the selection toolbar's two destinations, a real side-chat answer, pending annotation and handback chips, and context bubbles in sent messages / 补拍主图:同屏展示划选菜单的两种去向、真实侧聊回答、待发送的批注与回流标签,以及已发送消息中的上下文气泡。
20
+ - `context-preview.jpg`: a compact preview with the selected passage, editable note, and horizontal context chips / 紧凑悬浮层中的原文、可编辑注解与横向标签。
21
+ - `selection.jpg`: selected text and the two annotation destinations, taken from the recording / 从录屏提取的划选画面与两种批注去向。
22
+ - `sidechat.jpg`: a real side-chat answer and the hovered reply-toolbar handback icon / 真实侧聊回答与悬停中的回流图标。
23
+ - `demo.gif`, `demo.mp4`: the same approximately **43-second** continuous workflow / 同一段约 **43 秒**的连续操作。
24
+ - `hero.svg`, `hero-en.svg` and their `-compact.svg` variants: vector brand covers; regenerate with `python3 scripts/build-brand-assets.py` / 品牌矢量封面,可用该命令重新生成。
25
+
26
+ ## Capture and distribution / 录制与展示
27
+
28
+ The real interface uses the host's **light theme** and **18 px** conversation font. The hero uses a **1440 × 780** viewport and is exported at 2160 × 1170 so the selection menu and both composers fit together. Other stills use a **1440 × 900** viewport, captured at 2× pixel density and exported at 2160 × 1350; the selection still is a native 1440 × 900 recording frame. MP4 is 1440 × 900 at 30 fps; GIF is 1120 × 700 at 12 fps. Encoding preserves the browser's frame timing without speeding up responses. A small pointer overlay follows actual mouse events in the recording; product controls and model replies are not redrawn or substituted.
29
+
30
+ 真实界面使用宿主的**浅色主题**和 **18 px** 会话字号。主图以 **1440 × 780** 视口补拍,导出为 2160 × 1170,让划选菜单和两侧输入框完整同屏。其余静态截图使用 **1440 × 900** 视口,按 2 倍像素密度采集后导出为 2160 × 1350;划选截图直接取自 1440 × 900 的录屏帧。MP4 为 1440 × 900 / 30 fps,GIF 为 1120 × 700 / 12 fps,均按浏览器帧时间编码,没有加速模型响应。录屏中仅添加跟随真实鼠标事件的小光标辅助层,没有重绘产品控件或替换模型回答。
31
+
32
+ [`screenshots.json`](../../screenshots.json) declares the storefront gallery. The [catalog's screenshot convention](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin/blob/main/contributing.md#screenshots--截图optional-recommended--可选推荐) resolves those paths from this repository, and the next catalog build refreshes the gallery. Existing screenshot paths remain available for cached catalogs.
33
+
34
+ [`screenshots.json`](../../screenshots.json) 声明商店展示顺序。[商店截图约定](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin/blob/main/contributing.md#screenshots--截图optional-recommended--可选推荐) 会从本仓库读取这些路径,下一次索引构建时更新图集;原有图片路径继续提供新版内容,供已缓存的索引读取。
35
+
36
+ For future captures, use a fresh isolated DSH home, install the published plugin with the official CLI, verify the active bundles, and run the complete workflow against the official model API. Keep credentials, launch tokens, private conversations, raw frames, and recording logs out of public assets. The older `capture-demo.mjs` and `capture-video.mjs` scripts target historical layouts and synthetic sessions; they do not reproduce this recording unchanged.
37
+
38
+ 后续重录应使用全新隔离的 DSH home,通过官方 CLI 安装已发布插件,核对实际加载的构建,并调用官方模型走完完整流程。凭证、启动 token、私人会话、原始帧和录制日志不进入公开素材。旧 `capture-demo.mjs`、`capture-video.mjs` 面向历史布局与合成会话,不能原样用于复现本次录制。
package/lib/client.js CHANGED
@@ -611,7 +611,7 @@ window.__ModuleLoader__.load({
611
611
  let dockRegistered = false;
612
612
  let report = {
613
613
  versions: {
614
- sidenote: "0.7.2",
614
+ sidenote: "0.7.3",
615
615
  dsh: "unknown",
616
616
  betterSidebar: null
617
617
  },
@@ -1262,15 +1262,15 @@ window.__ModuleLoader__.load({
1262
1262
  document.head.appendChild(tag);
1263
1263
  }
1264
1264
  var diagnostics_module_css_default = {
1265
+ "setting": "tGe0LW_setting",
1266
+ "list": "tGe0LW_list",
1267
+ "header": "tGe0LW_header",
1265
1268
  "versions": "tGe0LW_versions",
1266
- "trigger": "tGe0LW_trigger",
1267
1269
  "actions": "tGe0LW_actions",
1268
- "panel": "tGe0LW_panel",
1270
+ "trigger": "tGe0LW_trigger",
1269
1271
  "settingTitle": "tGe0LW_settingTitle",
1270
- "setting": "tGe0LW_setting",
1271
- "header": "tGe0LW_header",
1272
- "description": "tGe0LW_description",
1273
- "list": "tGe0LW_list"
1272
+ "panel": "tGe0LW_panel",
1273
+ "description": "tGe0LW_description"
1274
1274
  };
1275
1275
  //#endregion
1276
1276
  //#region src/client/diagnostics/index.tsx
@@ -1855,17 +1855,19 @@ window.__ModuleLoader__.load({
1855
1855
  const sideChatBridge = { current: null };
1856
1856
  //#endregion
1857
1857
  //#region src/client/chat/transcript.ts
1858
- /** ContentBlock[] → 纯文本:text 块拼接;image 块降级占位;其余忽略。 */
1858
+ /** Protocol readers need actual text, not attachment preview labels before it.
1859
+ * Native Conversation renders images; only an image-only message needs a label. */
1859
1860
  function contentTextOf(content) {
1860
1861
  if (!Array.isArray(content)) return "";
1861
1862
  const parts = [];
1863
+ let hasImage = false;
1862
1864
  for (const block of content) {
1863
1865
  if (typeof block !== "object" || block === null) continue;
1864
1866
  const b = block;
1865
1867
  if (b.type === "text" && typeof b.text === "string") parts.push(b.text);
1866
- else if (b.type === "image") parts.push(t("imagePlaceholder"));
1868
+ else if (b.type === "image") hasImage = true;
1867
1869
  }
1868
- return parts.join("\n");
1870
+ return parts.join("\n") || (hasImage ? t("imagePlaceholder") : "");
1869
1871
  }
1870
1872
  function seqKey(prefix, node) {
1871
1873
  return `${prefix}:${typeof node.seq === "number" ? node.seq : "?"}`;
@@ -2331,29 +2333,29 @@ window.__ModuleLoader__.load({
2331
2333
  document.head.appendChild(tag);
2332
2334
  }
2333
2335
  var sidechat_module_css_default = {
2334
- "emptyText": "_5KEEsG_emptyText",
2335
- "headerSide": "_5KEEsG_headerSide",
2336
- "nativeConversation": "_5KEEsG_nativeConversation",
2337
- "errorRow": "_5KEEsG_errorRow",
2336
+ "nativeToolbarActions": "_5KEEsG_nativeToolbarActions",
2338
2337
  "nativeAction": "_5KEEsG_nativeAction",
2338
+ "stateScreen": "_5KEEsG_stateScreen",
2339
+ "nativeHost": "_5KEEsG_nativeHost",
2340
+ "root": "_5KEEsG_root",
2341
+ "mainContext": "_5KEEsG_mainContext",
2342
+ "emptyIcon": "_5KEEsG_emptyIcon",
2339
2343
  "stateDetail": "_5KEEsG_stateDetail",
2340
- "progressEntries": "_5KEEsG_progressEntries",
2344
+ "visibilitySetting": "_5KEEsG_visibilitySetting",
2345
+ "nativeConversation": "_5KEEsG_nativeConversation",
2346
+ "chatView": "_5KEEsG_chatView",
2347
+ "historyToggle": "_5KEEsG_historyToggle",
2341
2348
  "contextChevron": "_5KEEsG_contextChevron",
2349
+ "progressEntries": "_5KEEsG_progressEntries",
2342
2350
  "nativeToolbar": "_5KEEsG_nativeToolbar",
2343
- "mainContext": "_5KEEsG_mainContext",
2344
- "root": "_5KEEsG_root",
2345
- "nativeHost": "_5KEEsG_nativeHost",
2346
- "contextHint": "_5KEEsG_contextHint",
2347
- "visibilitySetting": "_5KEEsG_visibilitySetting",
2351
+ "emptyTitle": "_5KEEsG_emptyTitle",
2348
2352
  "progressEntry": "_5KEEsG_progressEntry",
2353
+ "contextHint": "_5KEEsG_contextHint",
2349
2354
  "reflowAction": "_5KEEsG_reflowAction",
2350
- "emptyIcon": "_5KEEsG_emptyIcon",
2351
- "nativeToolbarActions": "_5KEEsG_nativeToolbarActions",
2352
2355
  "contextChevronOpen": "_5KEEsG_contextChevronOpen",
2353
- "stateScreen": "_5KEEsG_stateScreen",
2354
- "emptyTitle": "_5KEEsG_emptyTitle",
2355
- "historyToggle": "_5KEEsG_historyToggle",
2356
- "chatView": "_5KEEsG_chatView"
2356
+ "emptyText": "_5KEEsG_emptyText",
2357
+ "errorRow": "_5KEEsG_errorRow",
2358
+ "headerSide": "_5KEEsG_headerSide"
2357
2359
  };
2358
2360
  //#endregion
2359
2361
  //#region src/client/sidechat/NativeConversation.tsx
@@ -5553,34 +5555,34 @@ ${entries.map((entry) => {
5553
5555
  document.head.appendChild(tag);
5554
5556
  }
5555
5557
  var annotate_module_css_default = {
5556
- "dshSidenoteHintIn": "_SVViG_dshSidenoteHintIn",
5557
- "deleteButton": "_SVViG_deleteButton",
5558
- "editorEdit": "_SVViG_editorEdit",
5558
+ "badge": "_SVViG_badge",
5559
+ "editorSpacer": "_SVViG_editorSpacer",
5560
+ "editorError": "_SVViG_editorError",
5561
+ "confirmButton": "_SVViG_confirmButton",
5562
+ "hint": "_SVViG_hint",
5563
+ "sentChipRow": "_SVViG_sentChipRow",
5559
5564
  "hintClose": "_SVViG_hintClose",
5565
+ "sentCardTitle": "_SVViG_sentCardTitle",
5566
+ "editorTextarea": "_SVViG_editorTextarea",
5567
+ "editorNew": "_SVViG_editorNew",
5560
5568
  "editorTarget": "_SVViG_editorTarget",
5561
- "sentChipRow": "_SVViG_sentChipRow",
5569
+ "editorFooter": "_SVViG_editorFooter",
5570
+ "cancelButton": "_SVViG_cancelButton",
5571
+ "dshSidenoteHintIn": "_SVViG_dshSidenoteHintIn",
5572
+ "sentChip": "_SVViG_sentChip",
5562
5573
  "editorInput": "_SVViG_editorInput",
5563
- "toolbarButton": "_SVViG_toolbarButton",
5564
5574
  "highlight": "_SVViG_highlight",
5565
- "sentChip": "_SVViG_sentChip",
5566
- "editorTextarea": "_SVViG_editorTextarea",
5567
- "editorNew": "_SVViG_editorNew",
5568
- "toolbarBelow": "_SVViG_toolbarBelow",
5569
- "badgeSent": "_SVViG_badgeSent",
5575
+ "toolbarButton": "_SVViG_toolbarButton",
5570
5576
  "toolbar": "_SVViG_toolbar",
5571
- "editorFooter": "_SVViG_editorFooter",
5577
+ "deleteButton": "_SVViG_deleteButton",
5572
5578
  "editorAsk": "_SVViG_editorAsk",
5573
- "confirmButton": "_SVViG_confirmButton",
5574
- "hint": "_SVViG_hint",
5575
- "badge": "_SVViG_badge",
5576
- "saveButton": "_SVViG_saveButton",
5579
+ "badgeSent": "_SVViG_badgeSent",
5580
+ "sentCardQuote": "_SVViG_sentCardQuote",
5577
5581
  "sentCardNote": "_SVViG_sentCardNote",
5578
- "cancelButton": "_SVViG_cancelButton",
5582
+ "saveButton": "_SVViG_saveButton",
5579
5583
  "editorAskRow": "_SVViG_editorAskRow",
5580
- "editorSpacer": "_SVViG_editorSpacer",
5581
- "editorError": "_SVViG_editorError",
5582
- "sentCardTitle": "_SVViG_sentCardTitle",
5583
- "sentCardQuote": "_SVViG_sentCardQuote"
5584
+ "toolbarBelow": "_SVViG_toolbarBelow",
5585
+ "editorEdit": "_SVViG_editorEdit"
5584
5586
  };
5585
5587
  //#endregion
5586
5588
  //#region src/client/annotate/hint.tsx
@@ -6393,34 +6395,34 @@ ${entries.map((entry) => {
6393
6395
  document.head.appendChild(tag);
6394
6396
  }
6395
6397
  var annotations_module_css_default = {
6398
+ "chipClearAll": "SVnebq_chipClearAll",
6399
+ "sentChips": "SVnebq_sentChips",
6400
+ "chipDismissShade": "SVnebq_chipDismissShade",
6396
6401
  "storageNotice": "SVnebq_storageNotice",
6402
+ "contextText": "SVnebq_contextText",
6403
+ "contextAppear": "SVnebq_contextAppear",
6404
+ "chip": "SVnebq_chip",
6405
+ "contextList": "SVnebq_contextList",
6406
+ "contextActions": "SVnebq_contextActions",
6407
+ "contextLabel": "SVnebq_contextLabel",
6397
6408
  "contextAction": "SVnebq_contextAction",
6398
- "userContextHost": "SVnebq_userContextHost",
6399
- "chipDismissShade": "SVnebq_chipDismissShade",
6400
6409
  "sentChipGroup": "SVnebq_sentChipGroup",
6410
+ "userContextHost": "SVnebq_userContextHost",
6401
6411
  "sentChip": "SVnebq_sentChip",
6402
- "contextFooter": "SVnebq_contextFooter",
6403
- "sentContext": "SVnebq_sentContext",
6412
+ "contextItem": "SVnebq_contextItem",
6404
6413
  "sentChevronOpen": "SVnebq_sentChevronOpen",
6405
- "contextPanel": "SVnebq_contextPanel",
6406
- "contextAppear": "SVnebq_contextAppear",
6407
- "sentChevron": "SVnebq_sentChevron",
6408
- "contextEditor": "SVnebq_contextEditor",
6409
- "contextNumber": "SVnebq_contextNumber",
6410
- "contextText": "SVnebq_contextText",
6411
- "sentChips": "SVnebq_sentChips",
6412
- "contextContent": "SVnebq_contextContent",
6414
+ "contextFooter": "SVnebq_contextFooter",
6415
+ "contextSource": "SVnebq_contextSource",
6413
6416
  "sentPreview": "SVnebq_sentPreview",
6417
+ "contextNumber": "SVnebq_contextNumber",
6418
+ "contextEditor": "SVnebq_contextEditor",
6419
+ "sentChevron": "SVnebq_sentChevron",
6414
6420
  "chipMain": "SVnebq_chipMain",
6415
- "contextItem": "SVnebq_contextItem",
6416
- "contextLabel": "SVnebq_contextLabel",
6417
- "chipWrap": "SVnebq_chipWrap",
6418
- "contextActions": "SVnebq_contextActions",
6419
- "contextSource": "SVnebq_contextSource",
6420
- "chipClearAll": "SVnebq_chipClearAll",
6421
- "chip": "SVnebq_chip",
6421
+ "sentContext": "SVnebq_sentContext",
6422
6422
  "chipDismiss": "SVnebq_chipDismiss",
6423
- "contextList": "SVnebq_contextList"
6423
+ "contextPanel": "SVnebq_contextPanel",
6424
+ "contextContent": "SVnebq_contextContent",
6425
+ "chipWrap": "SVnebq_chipWrap"
6424
6426
  };
6425
6427
  //#endregion
6426
6428
  //#region src/client/annotations/chip.tsx
@@ -21,7 +21,8 @@ export interface ChatMessage {
21
21
  /** 被打断冻结的 assistant 输出(渲染「已停止」标记)。 */
22
22
  interrupted?: boolean;
23
23
  }
24
- /** ContentBlock[] → 纯文本:text 块拼接;image 块降级占位;其余忽略。 */
24
+ /** Protocol readers need actual text, not attachment preview labels before it.
25
+ * Native Conversation renders images; only an image-only message needs a label. */
25
26
  export declare function contentTextOf(content: unknown): string;
26
27
  /**
27
28
  * 单个 ConversationNode → ChatMessage;返回 null = 面板不渲染
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-sidenote",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "Follow the tangent. Keep the thread. Annotate, explore on the side, and bring answers back to DeepSeek Harness. / 思路可以分岔,主线始终向前。划选注释、侧边追问,再把结论带回正在推进的任务。",
5
5
  "icon": "docs/assets/logo.svg",
6
6
  "type": "module",
@@ -31,17 +31,19 @@ interface LooseBlock {
31
31
  name?: unknown
32
32
  }
33
33
 
34
- /** ContentBlock[] → 纯文本:text 块拼接;image 块降级占位;其余忽略。 */
34
+ /** Protocol readers need actual text, not attachment preview labels before it.
35
+ * Native Conversation renders images; only an image-only message needs a label. */
35
36
  export function contentTextOf(content: unknown): string {
36
37
  if (!Array.isArray(content)) return ''
37
38
  const parts: string[] = []
39
+ let hasImage = false
38
40
  for (const block of content) {
39
41
  if (typeof block !== 'object' || block === null) continue
40
42
  const b = block as LooseBlock
41
43
  if (b.type === 'text' && typeof b.text === 'string') parts.push(b.text)
42
- else if (b.type === 'image') parts.push(t('imagePlaceholder'))
44
+ else if (b.type === 'image') hasImage = true
43
45
  }
44
- return parts.join('\n')
46
+ return parts.join('\n') || (hasImage ? t('imagePlaceholder') : '')
45
47
  }
46
48
 
47
49
  function seqKey(prefix: string, node: Record<string, unknown>): string {