@benz-ai-x/dsh-md-preview 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,110 +1,138 @@
1
+ [English](README.md) | [中文](README.zh.md)
2
+
1
3
  # @benz-ai-x/dsh-md-preview
2
4
 
3
- DSH Web GUI 插件:点击对话中出现的 Markdown 文档,在对话右侧打开渲染后的预览面板。
5
+ **DSH (DeepSeek Harness) Web GUI plugin markdown preview, editing & workspace file browser beside the chat.** Preview rendered markdown and plain-text files, edit with conflict-guarded saves, and browse the session workspace tree without leaving the conversation.
4
6
 
5
7
  [![npm](https://img.shields.io/npm/v/@benz-ai-x/dsh-md-preview)](https://www.npmjs.com/package/@benz-ai-x/dsh-md-preview)
6
8
  [![GitHub](https://img.shields.io/badge/repo-benz--ai--x%2Fdsh--md--preview-24292e?logo=github)](https://github.com/benz-ai-x/dsh-md-preview)
7
9
 
8
- ## 效果
10
+ ## Features
9
11
 
10
- - 回合产出文件 chip 行中的 `.md` / `.markdown` 文档:点击打开右侧预览面板,渲染 GFM、代码高亮和 TeX
11
- - 每条助手消息的操作区新增「预览文档」按钮,列出该回合产出的 Markdown 文档。
12
- - Markdown 产出文件保持原有行为(交给系统打开)。
13
- - 面板可关闭、可拖宽(320–1280 px,默认 500);拖出的宽度在本次应用会话内保持。
14
- - 没有预览目标时面板不渲染。
15
- - **编辑**:面板「编辑」进入 CodeMirror 编辑器(行号、GFM 高亮、Cmd/Ctrl-S 保存),「保存」写回工作区、显示「✓ 已保存」提示并回到渲染视图,「取消编辑」丢弃草稿;只编辑已存在的文件。保存失败(非冲突)会显示错误码并提供【重试】。
16
- - **冲突保护**:保存时若文件已被其它方(agent、其它会话、外部编辑器)修改,提示「文件已变化」,由你选择【重新加载】或【强制覆盖】;带未保存修改关闭面板会先询问。
17
- - **工作区浏览**:面板头部「工作区」进入目录树(懒展开、加载/空/失败三态);单击 `.md` 富渲染、`.txt` 等纯文本等宽展示、其它类型明确提示不支持;当前文档在树中高亮并自动定位;支持方向键/Enter 键盘遍历;头部路径面包屑。
12
+ - Markdown chips in the produced-files row of a turn open a right-docked preview panel rendering GFM, syntax-highlighted code, and TeX.
13
+ - A per-message "Preview documents" action lists that turn's markdown documents.
14
+ - Non-markdown deliverables keep the shipped open-on-desktop behavior.
15
+ - The panel is closable and draggable (320–1280 px, default 500); the dragged width persists for the app session.
16
+ - The panel renders nothing while no preview target is set.
17
+ - **Editing** — the panel's Edit action enters a CodeMirror editor (line numbers, GFM highlighting, Cmd/Ctrl-S save); Save writes back to the workspace, flashes a "Saved" toast, and returns to the rendered view; Cancel discards the draft. Only existing files edit. Non-conflict save failures show the failure code with a Retry action.
18
+ - **Conflict guard** — saving over a file that changed elsewhere (another session, the agent, an external editor) prompts "the file changed elsewhere": Reload or Overwrite; closing with unsaved edits asks first.
19
+ - **Workspace browser** — the panel header's Workspace action enters a directory tree of the session workspace (lazy expansion, loading/empty/failed states); single-click renders `.md` rich, `.txt` and other text monospace, other types a clear unsupported notice; the current document highlights and auto-reveals in the tree; full keyboard traversal (arrows/Enter); the header shows the path breadcrumb. Expanded directories silently revalidate on every re-entry (and from the tree's refresh button) — the agent keeps producing files mid-conversation, and a failed refresh never blanks what's on screen.
20
+ - **Outline** — the header's outline popover lists the document's ATX headings (fenced code never counts); clicking scrolls the rendered heading in the view face and jumps the cursor to the source line in the edit face.
21
+ - **Editor find** — the edit face carries a CodeMirror search panel (header button and Mod/Ctrl-F).
22
+ - **Mermaid diagrams** — fenced ` ```mermaid ` blocks render as diagrams after the document settles; the block banner stays (copy still reads the source), and any failure falls back to the plain code block. Mermaid is inlined into the client bundle but evaluated lazily (first diagram pays the parse cost; bundle ~3.9 MB minified / ~1.1 MB gzip).
18
23
 
19
- ## 安装
24
+ ## Install
20
25
 
21
- 要求 DSH 基线 `0.1.2-alpha.3`( peerDependencies 所列版本) web profile
26
+ Requires DSH baseline `0.1.2-rc.1` (see peerDependencies) and a web profile.
22
27
 
23
28
  ```sh
24
29
  dsh plugin --profile <name> add @benz-ai-x/dsh-md-preview
25
- dsh --profile <name> --dump-config # 应出现 id: md-preview 的行
26
- dsh --profile <name> # 打开 Web GUI;回合产出 .md 后点击 chip 预览
30
+ dsh --profile <name> --dump-config # expect the id: md-preview row
31
+ dsh --profile <name> # open the Web GUI; click a chip after a turn produces .md
27
32
  dsh plugin --profile <name> remove @benz-ai-x/dsh-md-preview
28
33
  ```
29
34
 
30
- ## 配置
35
+ ### Three install forms (per the [DSH publish spec](https://github.com/deepseek-ai/deepseek-harness/blob/main/docs/user/develop/basic/publish.md))
36
+
37
+ | Form | Command | Status |
38
+ | --- | --- | --- |
39
+ | npm (recommended) | `dsh plugin --profile <name> add @benz-ai-x/dsh-md-preview` | ✅ prebuilt, works out of the box |
40
+ | tarball | `dsh plugin --profile <name> add ./benz-ai-x-dsh-md-preview-<ver>.tgz` (from `pnpm pack:publishable`) | ✅ prebuilt, no build approval needed |
41
+ | Git | `dsh plugin --profile <name> add github:benz-ai-x/dsh-md-preview#<sha>` | ✅ builds from source via the package's self-contained `prepare` (transpile-only; no type declarations ship on this form) — see below |
42
+
43
+ Git installs fetch source, and pnpm refuses to run a git dependency's `prepare` until the package is explicitly allowed. After the first `add` fails, copy the package key pnpm printed into the profile's `pnpm-workspace.yaml`:
44
+
45
+ ```yaml
46
+ allowBuilds:
47
+ '@benz-ai-x/dsh-md-preview': true
48
+ ```
49
+
50
+ then re-run `add`. Allowing a build executes the package's code on your machine at install time — allow only sources you trust, and pin a commit (`#<sha>`) so a later push cannot silently change what runs.
51
+
52
+ ## Configuration
31
53
 
32
54
  ```yaml
33
55
  - id: md-preview
34
56
  name: '@benz-ai-x/dsh-md-preview'
35
57
  config:
36
- maxBytes: 1048576 # 单文件读取上限(字节)
58
+ maxBytes: 1048576 # per-file read/write cap in bytes
37
59
  allowedExtensions: ['.md', '.markdown']
38
60
  ```
39
61
 
40
- | 字段 | 类型 | 默认 | 说明 |
62
+ | Field | Type | Default | Notes |
41
63
  | --- | --- | --- | --- |
42
- | `maxBytes` | number | `1048576` | 单文件读/写上限,超出返回 `too-large` |
43
- | `allowedExtensions` | string[] | `[".md", ".markdown"]` | 可编辑的扩展名白名单 |
44
- | `previewExtensions` | string[] | `[".md", ".markdown", ".txt"]` | 可预览的扩展名(可编辑集的超集;纯文本成员只读展示) |
64
+ | `maxBytes` | number | `1048576` | per-file read/write cap; exceeded returns `too-large` |
65
+ | `allowedExtensions` | string[] | `[".md", ".markdown"]` | extensions eligible for editing |
66
+ | `previewExtensions` | string[] | `[".md", ".markdown", ".txt"]` | extensions eligible for preview (a superset of the editable set; plain-text members render read-only) |
45
67
 
46
- ## 失败码
68
+ ## Failure codes
47
69
 
48
- 读取失败时面板显示 `md-preview/<reason>`。所有失败码:
70
+ The panel shows `md-preview/<reason>` on failure. All codes:
49
71
 
50
- | | 含义 |
72
+ | Code | Meaning |
51
73
  | --- | --- |
52
- | `md-preview/bad-request` | path 为空或非法;或保存时既无指纹也未强制 |
53
- | `md-preview/unknown-session` | 会话不存在 |
54
- | `md-preview/no-workspace` | 会话没有工作目录 |
55
- | `md-preview/unsupported-extension` | 扩展名不在白名单 |
56
- | `md-preview/forbidden` | 路径超出会话工作区 |
57
- | `md-preview/not-found` | 文件不存在(编辑只针对已存在文件) |
58
- | `md-preview/too-large` | 文件(读取)或内容(写入)超过 `maxBytes` |
59
- | `md-preview/conflict` | 保存时文件已变化(指纹不匹配且未强制) |
60
- | `md-preview/unavailable` | 读/写过程发生 IO 错误 |
61
-
62
- ## 已知限制
63
-
64
- - 正文中内联提到的 `.md` 文件名仍走系统打开( ui-deliverables 所有,不归本插件)
65
- - 面板悬浮在对话右侧,不替换三栏布局。
66
- - 用户上传的文档附件不可预览(目前没有对应的会话面)
67
-
68
- ## 开发(source-linked)
74
+ | `md-preview/bad-request` | path empty or unusable; or a save with neither fingerprint nor force |
75
+ | `md-preview/unknown-session` | session does not exist |
76
+ | `md-preview/no-workspace` | session has no working directory |
77
+ | `md-preview/unsupported-extension` | extension outside the allowlist |
78
+ | `md-preview/forbidden` | path escapes the session workspace |
79
+ | `md-preview/not-found` | file does not exist (editing targets existing files only) |
80
+ | `md-preview/too-large` | file (read) or content (write) exceeds `maxBytes` |
81
+ | `md-preview/conflict` | file changed since the read backing the save (no force) |
82
+ | `md-preview/unavailable` | IO error during read/write |
83
+
84
+ ## Known limits
85
+
86
+ - Inline prose mentions of `.md` files still open on the desktop (owned by ui-deliverables, not this plugin).
87
+ - The panel floats above the details column; it does not replace the three-column grid.
88
+ - Uploaded document attachments are not previewable (no transcript surface today).
89
+ - The outline lists ATX headings only (setext forms render but stay out of the popover).
90
+ - Mermaid renders with its default theme; documents mixing indented code blocks with fenced ones skip the diagram pass entirely (order-parity safety check).
91
+
92
+ ## Development (source-linked)
69
93
 
70
94
  ```sh
71
95
  pnpm install
72
96
  pnpm verify # context:check:strict + typecheck + test + build + built:check
73
- pnpm context:sync # Harness 检出移动后重写 link 并刷新 lockfile
74
- pnpm watch:client # 客户端 bundle 热构建
97
+ pnpm context:link # source-linked development: rewrite link: at the harness checkout (registry by default)
98
+ pnpm watch:client # client bundle watch build
75
99
  ```
76
100
 
77
- ### 结构
101
+ ### Structure
78
102
 
79
- | 部分 | 位置 | 说明 |
103
+ | Part | Location | Notes |
80
104
  | --- | --- | --- |
81
- | Host Remote | `src/remote.ts` | `mdPreview/read(sessionId, path, signal)`;工作区限域、扩展名白名单、字节上限 |
82
- | Remote contribution | `src/typert/remote-client.ts` | 手工维护的浏览器端描述符(生成器产物的等价物) |
83
- | 浏览器入口 | `src/client/index.ts` | 挂载 Remote + 注册三个 Slot 贡献 |
84
- | 预览面板 | `src/client/PreviewOverlay.tsx` | `shell.overlay`(list,增量);编辑/冲突/未保存状态机 |
85
- | 编辑器 | `src/client/editor.tsx` | CodeMirror 6(精选扩展集,构建期内联,client bundle ~400 kB minified) |
86
- | chip 行接管 | `src/client/MdChips.tsx` | `conversation.chat.turnTail`(chain,仅认领含 Markdown 的回合) |
87
- | 消息操作 | `src/client/PreviewAction.tsx` | `conversation.chat.assistant-actions`(list,增量) |
88
-
89
- ### 真实 profile 验证(本地检出)
105
+ | Host Remote | `src/remote.ts` | `mdPreview/read(sessionId, path, signal)`; workspace scoping, extension allowlists, byte caps |
106
+ | Remote contribution | `src/typert/remote-client.ts` | hand-maintained browser-side descriptors (generator-equivalent) |
107
+ | Browser entry | `src/client/index.ts` | mounts the Remote + registers three Slot contributions |
108
+ | Preview panel | `src/client/PreviewOverlay.tsx` | `shell.overlay` (list, additive); rendering + geometry only |
109
+ | Session machine | `src/client/preview-session.ts` | pure reducer for read/edit/save/prompts |
110
+ | Editor | `src/client/editor.tsx` | CodeMirror 6 (curated extensions incl. the search panel, inlined at build) |
111
+ | Workspace tree | `src/client/WorkspaceBrowser.tsx` | lazy tree with highlight/auto-reveal/keyboard and silent revalidation |
112
+ | Outline | `src/client/outline.ts` | ATX heading scan + rendered-heading resolution |
113
+ | Diagram pass | `src/client/diagrams.ts` | post-render mermaid enhancement, fail-soft to the code block |
114
+ | Chip row | `src/client/MdChips.tsx` | `conversation.chat.turnTail` (chain; claims markdown-bearing turns) |
115
+ | Message action | `src/client/PreviewAction.tsx` | `conversation.chat.assistant-actions` (list, additive) |
116
+
117
+ ### Real-profile verification (local checkout)
90
118
 
91
119
  ```sh
92
120
  pnpm build
93
121
  dsh plugin --profile <name> add ./dsh-md-preview
94
122
  dsh --profile <name> --dump-config
95
- dsh --profile <name> # 打开 Web GUI,写一个 README.md 产出并点击 chip
123
+ dsh --profile <name> # open the Web GUI, produce a README.md and click the chip
96
124
  dsh plugin --profile <name> remove @benz-ai-x/dsh-md-preview
97
125
  ```
98
126
 
99
- ### 打包与发布
127
+ ### Pack & publish
100
128
 
101
129
  ```sh
102
- pnpm pack:publishable # 打出净化 manifest tarball 并复检( devDeps、无 link:/workspace:)
103
- pnpm publish:registry # 以同一净化流程发布到 npm
130
+ pnpm pack:publishable # registry-clean tarball + self-check (no devDeps, no link:/workspace:)
131
+ pnpm publish:registry # publish via the same cleaned-manifest flow
104
132
  ```
105
133
 
106
- source-linked 验证证明与固定 Harness 检出( `dsh-reference.lock.json`)的兼容性;发布形态以 packed tarball 在干净 profile 中的安装/启动/移除冒烟为准。
134
+ Source-linked verification proves compatibility with the pinned harness checkout (see `dsh-reference.lock.json`); the publish form is proven by the packed-tarball profile smoke.
107
135
 
108
- ## 许可证
136
+ ## License
109
137
 
110
138
  MIT
package/README.zh.md ADDED
@@ -0,0 +1,138 @@
1
+ [English](README.md) | 中文
2
+
3
+ # @benz-ai-x/dsh-md-preview
4
+
5
+ DSH Web GUI 插件:点击对话中出现的 Markdown 文档,在对话右侧打开渲染后的预览面板;支持受守卫编辑与工作区目录树浏览。
6
+
7
+ [![npm](https://img.shields.io/npm/v/@benz-ai-x/dsh-md-preview)](https://www.npmjs.com/package/@benz-ai-x/dsh-md-preview)
8
+ [![GitHub](https://img.shields.io/badge/repo-benz--ai--x%2Fdsh--md--preview-24292e?logo=github)](https://github.com/benz-ai-x/dsh-md-preview)
9
+
10
+ ## 效果
11
+
12
+ - 回合产出文件 chip 行中的 `.md` / `.markdown` 文档:点击打开右侧预览面板,渲染 GFM、代码高亮和 TeX。
13
+ - 每条助手消息的操作区新增「预览文档」按钮,列出该回合产出的 Markdown 文档。
14
+ - 非 Markdown 产出文件保持原有行为(交给系统打开)。
15
+ - 面板可关闭、可拖宽(320–1280 px,默认 500);拖出的宽度在本次应用会话内保持。
16
+ - 没有预览目标时面板不渲染。
17
+ - **编辑**:面板「编辑」进入 CodeMirror 编辑器(行号、GFM 高亮、Cmd/Ctrl-S 保存),「保存」写回工作区、显示「✓ 已保存」提示并回到渲染视图,「取消编辑」丢弃草稿;只编辑已存在的文件。保存失败(非冲突)会显示错误码并提供【重试】。
18
+ - **冲突保护**:保存时若文件已被其它方(agent、其它会话、外部编辑器)修改,提示「文件已变化」,由你选择【重新加载】或【强制覆盖】;带未保存修改关闭面板会先询问。
19
+ - **工作区浏览**:面板头部「工作区」进入目录树(懒展开、加载/空/失败三态);单击 `.md` 富渲染、`.txt` 等纯文本等宽展示、其它类型明确提示不支持;当前文档在树中高亮并自动定位;支持方向键/Enter 键盘遍历;头部路径面包屑。已展开目录在每次重进浏览脸时**静默重验**(树工具栏也有刷新按钮)——agent 会在会话中途持续产出文件,刷新失败绝不清空现有列表。
20
+ - **大纲导航**:头部「大纲」弹层列出文档的 ATX 标题(代码围栏内的 `#` 不算);点击后查看脸滚动到渲染标题、编辑脸跳转光标到源行。
21
+ - **编辑器查找**:编辑脸带 CodeMirror 搜索面板(头部按钮与 Mod/Ctrl-F)。
22
+ - **Mermaid 图表**:` ```mermaid ` 围栏块在文档渲染定型后增强为图表;块横幅保留(复制仍取源码),任何失败回退纯代码块。mermaid 内联进 client bundle 但**惰性求值**(首个图表才付解析成本;bundle 约 3.9 MB minified / 1.1 MB gzip)。
23
+
24
+ ## 安装
25
+
26
+ 要求 DSH 基线 `0.1.2-rc.1`(即 peerDependencies 所列版本)和 web profile。
27
+
28
+ ```sh
29
+ dsh plugin --profile <name> add @benz-ai-x/dsh-md-preview
30
+ dsh --profile <name> --dump-config # 应出现 id: md-preview 的行
31
+ dsh --profile <name> # 打开 Web GUI;回合产出 .md 后点击 chip 预览
32
+ dsh plugin --profile <name> remove @benz-ai-x/dsh-md-preview
33
+ ```
34
+
35
+ ### 三种安装形态(依 [DSH 打包与安装规范](https://github.com/deepseek-ai/deepseek-harness/blob/main/docs/user/develop/basic/publish.zh.md))
36
+
37
+ | 形态 | 命令 | 状态 |
38
+ | --- | --- | --- |
39
+ | npm(推荐) | `dsh plugin --profile <name> add @benz-ai-x/dsh-md-preview` | ✅ 预构建产物,即装即用 |
40
+ | tarball | `dsh plugin --profile <name> add ./benz-ai-x-dsh-md-preview-<ver>.tgz`(tarball 由源码 `pnpm pack:publishable` 产出) | ✅ 预构建产物,无需任何构建授权 |
41
+ | Git 直装 | `dsh plugin --profile <name> add github:benz-ai-x/dsh-md-preview#<sha>` | ✅ 由包自带的自包含 `prepare` 从源码构建(纯转译,此形态不带类型声明)——见下文 |
42
+
43
+ git 安装拉取的是源码,pnpm 在得到显式允许前拒绝运行 git 依赖的 `prepare`。首次 `add` 失败后,把 pnpm 打印的确切包键复制进该 profile 的 `pnpm-workspace.yaml`:
44
+
45
+ ```yaml
46
+ allowBuilds:
47
+ '@benz-ai-x/dsh-md-preview': true
48
+ ```
49
+
50
+ 然后重新执行 `add`。授权构建 = 允许该包的代码在安装时于你的机器上执行 —— 只对可信源码授权,并用 `#<sha>` 锁定 commit,让后续推送无法悄悄改变实际运行的内容。
51
+
52
+ ## 配置
53
+
54
+ ```yaml
55
+ - id: md-preview
56
+ name: '@benz-ai-x/dsh-md-preview'
57
+ config:
58
+ maxBytes: 1048576 # 单文件读取上限(字节)
59
+ allowedExtensions: ['.md', '.markdown']
60
+ ```
61
+
62
+ | 字段 | 类型 | 默认 | 说明 |
63
+ | --- | --- | --- | --- |
64
+ | `maxBytes` | number | `1048576` | 单文件读/写上限,超出返回 `too-large` |
65
+ | `allowedExtensions` | string[] | `[".md", ".markdown"]` | 可编辑的扩展名白名单 |
66
+ | `previewExtensions` | string[] | `[".md", ".markdown", ".txt"]` | 可预览的扩展名(可编辑集的超集;纯文本成员只读展示) |
67
+
68
+ ## 失败码
69
+
70
+ 读取失败时面板显示 `md-preview/<reason>`。所有失败码:
71
+
72
+ | 码 | 含义 |
73
+ | --- | --- |
74
+ | `md-preview/bad-request` | path 为空或非法;或保存时既无指纹也未强制 |
75
+ | `md-preview/unknown-session` | 会话不存在 |
76
+ | `md-preview/no-workspace` | 会话没有工作目录 |
77
+ | `md-preview/unsupported-extension` | 扩展名不在白名单 |
78
+ | `md-preview/forbidden` | 路径超出会话工作区 |
79
+ | `md-preview/not-found` | 文件不存在(编辑只针对已存在文件) |
80
+ | `md-preview/too-large` | 文件(读取)或内容(写入)超过 `maxBytes` |
81
+ | `md-preview/conflict` | 保存时文件已变化(指纹不匹配且未强制) |
82
+ | `md-preview/unavailable` | 读/写过程发生 IO 错误 |
83
+
84
+ ## 已知限制
85
+
86
+ - 正文中内联提到的 `.md` 文件名仍走系统打开(归 ui-deliverables 所有,不归本插件)。
87
+ - 面板悬浮在对话右侧,不替换三栏布局。
88
+ - 用户上传的文档附件不可预览(目前没有对应的会话面)。
89
+ - 大纲只收 ATX 标题(setext 下划线式标题会渲染但不进弹层)。
90
+ - Mermaid 用默认主题;混用缩进代码块与围栏块的文档整体跳过图表增强(顺序对齐安全检查)。
91
+
92
+ ## 开发(source-linked)
93
+
94
+ ```sh
95
+ pnpm install
96
+ pnpm verify # context:check:strict + typecheck + test + build + built:check
97
+ pnpm context:link # 需要源码联调时:重写 link: 指向 Harness 检出并刷新 lockfile(默认 registry)
98
+ pnpm watch:client # 客户端 bundle 热构建
99
+ ```
100
+
101
+ ### 结构
102
+
103
+ | 部分 | 位置 | 说明 |
104
+ | --- | --- | --- |
105
+ | Host Remote | `src/remote.ts` | `mdPreview/read(sessionId, path, signal)`;工作区限域、扩展名白名单、字节上限 |
106
+ | Remote contribution | `src/typert/remote-client.ts` | 手工维护的浏览器端描述符(生成器产物的等价物) |
107
+ | 浏览器入口 | `src/client/index.ts` | 挂载 Remote + 注册三个 Slot 贡献 |
108
+ | 预览面板 | `src/client/PreviewOverlay.tsx` | `shell.overlay`(list,增量);仅渲染 + 几何 |
109
+ | 会话机器 | `src/client/preview-session.ts` | 纯 reducer:读取/编辑/保存/提示的完整状态代数 |
110
+ | 编辑器 | `src/client/editor.tsx` | CodeMirror 6(精选扩展集含搜索面板,构建期内联) |
111
+ | 工作区树 | `src/client/WorkspaceBrowser.tsx` | 懒树:高亮/自动定位/键盘遍历 + 静默重验 |
112
+ | 大纲 | `src/client/outline.ts` | ATX 标题扫描 + 渲染标题定位 |
113
+ | 图表增强 | `src/client/diagrams.ts` | 渲染后 mermaid 增强,失败回退代码块 |
114
+ | chip 行接管 | `src/client/MdChips.tsx` | `conversation.chat.turnTail`(chain,仅认领含 Markdown 的回合) |
115
+ | 消息操作 | `src/client/PreviewAction.tsx` | `conversation.chat.assistant-actions`(list,增量) |
116
+
117
+ ### 真实 profile 验证(本地检出)
118
+
119
+ ```sh
120
+ pnpm build
121
+ dsh plugin --profile <name> add ./dsh-md-preview
122
+ dsh --profile <name> --dump-config
123
+ dsh --profile <name> # 打开 Web GUI,写一个 README.md 产出并点击 chip
124
+ dsh plugin --profile <name> remove @benz-ai-x/dsh-md-preview
125
+ ```
126
+
127
+ ### 打包与发布
128
+
129
+ ```sh
130
+ pnpm pack:publishable # 打出净化 manifest 的 tarball 并复检(无 devDeps、无 link:/workspace:)
131
+ pnpm publish:registry # 以同一净化流程发布到 npm
132
+ ```
133
+
134
+ source-linked 验证证明与固定 Harness 检出(见 `dsh-reference.lock.json`)的兼容性;发布形态以 packed tarball 在干净 profile 中的安装/启动/移除冒烟为准。
135
+
136
+ ## 许可证
137
+
138
+ MIT