dsh-doc-assistant 0.0.0-stage → 0.1.18

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 (57) hide show
  1. package/README.md +444 -2
  2. package/cordis.patch.yml +15 -0
  3. package/lib/client.js +10423 -0
  4. package/lib/index.js +12 -0
  5. package/package.json +46 -4
  6. package/src/client/10-dom.js +166 -0
  7. package/src/client/15-markdown.js +196 -0
  8. package/src/client/20-api.js +322 -0
  9. package/src/client/30-styles.js +260 -0
  10. package/src/client/40-revisions.js +1148 -0
  11. package/src/client/50-library.js +1407 -0
  12. package/src/client/60-reader.js +5617 -0
  13. package/src/client/70-shelf.js +1161 -0
  14. package/src/client/90-boot.js +75 -0
  15. package/src/client/THIRD_PARTY_NOTICES.md +25 -0
  16. package/src/host/chat.js +1053 -0
  17. package/src/host/config.js +283 -0
  18. package/src/host/convert.js +423 -0
  19. package/src/host/covers.js +1909 -0
  20. package/src/host/docir.js +1107 -0
  21. package/src/host/expansion.js +35 -0
  22. package/src/host/index.js +63 -0
  23. package/src/host/legacyWord.js +91 -0
  24. package/src/host/modelVision.js +44 -0
  25. package/src/host/ocr.js +163 -0
  26. package/src/host/ocr_vision.js +39 -0
  27. package/src/host/ocr_vision.swift +80 -0
  28. package/src/host/ocr_windows.ps1 +89 -0
  29. package/src/host/office.js +563 -0
  30. package/src/host/officeEditor.js +100 -0
  31. package/src/host/officeImages.js +269 -0
  32. package/src/host/office_tool.py +1600 -0
  33. package/src/host/pdfOutline.js +162 -0
  34. package/src/host/pdfText.js +799 -0
  35. package/src/host/preview.js +586 -0
  36. package/src/host/projects.js +418 -0
  37. package/src/host/revise.js +1229 -0
  38. package/src/host/revisionBoundary.js +45 -0
  39. package/src/host/revisionRebase.js +123 -0
  40. package/src/host/revisions.js +453 -0
  41. package/src/host/routes.js +1050 -0
  42. package/src/host/runtime.js +115 -0
  43. package/src/host/setup.js +48 -0
  44. package/src/host/shelf_files.js +189 -0
  45. package/src/host/tools.js +848 -0
  46. package/src/host/tree.js +417 -0
  47. package/src/host/upload.js +656 -0
  48. package/src/host/visionOcr.js +101 -0
  49. package/src/host/visualContext.js +248 -0
  50. package/src/host/wordLayout.js +131 -0
  51. package/src/host/wordSelection.js +114 -0
  52. package/src/host/writeback.js +397 -0
  53. package/src/host/writers/docx.js +65 -0
  54. package/src/host/writers/index.js +92 -0
  55. package/src/host/writers/pptx.js +54 -0
  56. package/src/host/writers/textrange.js +203 -0
  57. package/src/host/writers/xlsx.js +58 -0
package/README.md CHANGED
@@ -1,3 +1,445 @@
1
- # Temporary Holding Version
1
+ # dsh-doc-assistant(企业文档助手)
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ 把 DSH 变成一个**文档工作台**:按项目组织企业文档,在阅读器里边读边和 AI 交流;
4
+ 选中文字后引用到对话输入区,输入问题或个性化修改要求;也可以让 AI 润色、扩写或直接翻译,
5
+ 改动以**修订模式**高亮呈现,逐条**接受 / 撤回**,不需要的修订卡片可以删除。
6
+
7
+ 这是 [需求基线](</Users/stone/Desktop/ceshi/企业文档助手插件_需求梳理.md>) 的实现。
8
+
9
+ ---
10
+
11
+ ## 它解决什么
12
+
13
+ 传统做法是"复制一段 → 切到对话框 → 粘贴 → 提问 → 切回去对照"。文档一长,上下文就散了。
14
+ 本插件把阅读器和对话放在同一屏:**选区就是上下文,修订就是结果,接受才落盘。**
15
+
16
+ 三条设计原则:
17
+
18
+ 1. **AI 永远不直接改文件。** 改写只生成"修订"这种插件内部数据;只有用户点「接受」才写回磁盘。
19
+ 这让"反悔"成为一等公民,而不是靠备份文件兜底。
20
+ 2. **锚点是地基。** 所有格式先转成统一的 `DocIR`,每个文本片段都带源文件字符偏移。
21
+ 引用和改写共用同一套定位,生成修订前核对选区原文与文件中的位置。
22
+ 3. **除 PDF 与图片外,全部格式支持修订闭环。** 靠**两级修订模型**实现,不是给每种格式写一套功能。
23
+
24
+ ---
25
+
26
+ ## 架构
27
+
28
+ ```
29
+ ┌─ 宿主半(Node,跑在 DSH 进程里)─────────────────────────────┐
30
+ │ config.js 插件配置($DSH_HOME/doc-assistant/config.json,600)│
31
+ │ projects.js 项目注册表 + resolve() 唯一路径安全闸门 │
32
+ │ tree.js 目录列举 / 文件名搜索 / docCount │
33
+ │ revisions.js 修订持久化 + 落盘前快照 │
34
+ │ routes.js HTTP 路由(同源守卫 + accept 流水线) │
35
+ │ docir.js 格式判定 + 解析成 DocIR(含真实源偏移) │
36
+ │ writers/ 按格式插拔的落盘层 │
37
+ │ revise.js AI 改写通道(subagent / ctx.llm.stream) │
38
+ │ chat.js 插件自有对话(ctx.llm.stream,零会话足迹) │
39
+ │ covers.js 两级智能封面(启发式 + AI 增强,可失败降级) │
40
+ │ upload.js 文档上传(原子写 + 重名避让 + 格式校验) │
41
+ │ tools.js doc_* 模型侧工具 │
42
+ └───────────────────────────┬──────────────────────────────────┘
43
+ │ fetch /doc-assistant/*
44
+ ┌───────────────────────────┴──────────────────────────────────┐
45
+ │ 客户端半(浏览器,由 dev/build-client.mjs 从 src/client 生成)│
46
+ │ ./dom DOM 工具与图标 │
47
+ │ ./api HTTP 封装 + 语义化 API.* │
48
+ │ ./styles 样式(全部 --dsw-* 令牌,明暗自动跟随) │
49
+ │ ./revisions 词级 diff / 修订卡片 / 选中工具条 │
50
+ │ ./shelf 书架总览:分架书卡 + 封面渲染 + 上传入口 │
51
+ │ ./reader main 'doc-assistant' —— 顶栏 + 书架/阅读器切换 │
52
+ │ ./library SettingsWindow:齿轮打开的独立设置窗口 │
53
+ │ ./boot 装配(只注册 sidebar.panellist + main) │
54
+ └───────────────────────────────────────────────────────────────┘
55
+ ```
56
+
57
+ ### 挂在哪些插槽上
58
+
59
+ | 插槽 | id / key | 作用 |
60
+ |---|---|---|
61
+ | `main` | `doc-assistant` | ⭐ **整个文档工作台**:左「项目 + 文档树 + 大纲」/ 中正文 / 右 AI 对话 |
62
+ | `sidebar.panellist` | `doc-assistant` | 侧边栏图标「**企业文档助手**」,点击进入上面这个页面 |
63
+
64
+ **只有这两个。** 本插件**不注册任何 `conversation.*` 插槽** —— 文档功能全部归属插件自己的页面,
65
+ 右侧对话也是插件自有的(走本包的 `/chat/*` 路由),而不是 DSH 的会话。
66
+
67
+ > **为什么不挂在 `conversation.view`?**
68
+ > v1.x 曾把阅读器做成对话里的一个视图,靠它拿 DSH 的会话能力(`inputActions` / `useConversation`)。
69
+ > 但那会把文档功能塞进对话,且 `conversation.view` 由 `conversation.session` 声明 ——
70
+ > 用户切到别的主面板时它会被卸载,文档树只能挂在阅读器里自保。
71
+ > v2.0 按需求改为**插件自有页面 + 自有对话**,两个问题一起消失。
72
+ >
73
+ > **`main` 面板拿不到会话绑定怎么办?** 官方明确 `main` 只有保留的 `conversation` key 才绑定会话。
74
+ > 所以对话不走 DSH 会话,而是走插件自己的宿主通道 —— 用 `ctx.llm.stream()` 直连模型,
75
+ > **零会话足迹**,文档问答不会污染用户的任何对话历史。详见 `CONTRACT.md §13`。
76
+
77
+ ### 为什么对话要自带,而不是复用 DSH 会话
78
+
79
+ 客户端 `sessions` 服务确实暴露了 `SessionBinding.session.prompt()`,理论上能从 `main` 面板驱动真会话。
80
+ 但**渲染**会话流要自己消费 `eventSource` 并重建 tool-call / 流式 / 审批等全部 Chat 节点 ——
81
+ 那等于重写一遍 `client-ui-chat`。而需求要的是**文档问答**,不是通用 agent 会话。
82
+
83
+ 所以分工是:
84
+
85
+ | 能力 | 通道 | 理由 |
86
+ |---|---|---|
87
+ | **文档问答**(右栏对话) | `ctx.llm.stream()` 直连 | 快、省、零会话足迹 |
88
+ | **润色改写**(修订) | 一次性 subagent(有 agent 时)+ LLM 兜底 | 要 schema 级结构化保证,且**可审计** |
89
+
90
+ 两条通道都已在真机验证通过。
91
+
92
+ ### 两级修订模型
93
+
94
+ 「除 PDF 外都要修订」如果按格式各做一套,就是 4 套独立功能。拆成两层:
95
+
96
+ ```
97
+ 统一层(所有可写格式共用)
98
+ Revision 数据模型 · 三种呈现粒度 · 修订卡片
99
+ 接受 / 撤回 / 批量 / 撤销 · 持久化 · 并发保护 · 多轮迭代
100
+ │ 只有「接受」时才调用
101
+ 落盘层(Writer,按格式插拔)
102
+ TextRangeWriter → md / txt / html / code
103
+ DocxWriter → OOXML,写 w:ins / w:del(M2)
104
+ XlsxWriter → openpyxl 单元格(M2)
105
+ PptxWriter → python-pptx run(M2)
106
+ ```
107
+
108
+ 新增一种格式 = 实现一个 Writer(约 100~200 行),UI 与数据模型完全复用。
109
+
110
+ ---
111
+
112
+ ## 格式支持
113
+
114
+ | 格式 | 预览 | 选中提问 | 选中改写 | 修订 | 落盘 | 修订粒度 |
115
+ |---|---|---|---|---|---|---|
116
+ | `.md` `.txt` `.html` 代码 | ✅ | ✅ | ✅ | ✅ | ✅ | 行内词级 diff |
117
+ | `.docx` | ✅ | ✅ | ✅ | ✅ | ✅ OOXML 原生修订 | 行内词级 diff |
118
+ | `.xlsx` `.csv` | ✅ | ✅ | ✅ | ✅ | ✅ openpyxl | 单元格级 |
119
+ | `.pptx` | ✅ | ✅ | ✅ | ✅ | ✅ python-pptx | 形状段落级 |
120
+ | `.pdf` | ✅ | ✅ | ❌ | ❌ | ❌ 只读 | — |
121
+ | 图片 | ✅ | ❌ | ❌ | ❌ | ❌ | — |
122
+
123
+ > PDF 按需求决策为**只读**;图片没有文本层,物理上不存在"可改写的对象"。
124
+ > M1 已交付前四行中的文本类,Office 三件套在 M2。
125
+
126
+ ---
127
+
128
+ ## 安装
129
+
130
+ ### 通用排版保护与并行生成(0.1.18)
131
+
132
+ - 不同选区可以同时润色、扩写;每个任务独立保留选区原文、位置、模型及处理状态,完成顺序不影响结果。生成期间不会写入文档,接受时按文档逐次写入。
133
+ - 一条修订接受后,其他未改动选区沿插件自己的写入记录调整位置,再精确核对完整原文。相同选区的候选、交叠修改或无法追溯的外部保存不自动合并,避免覆盖文字。
134
+ - Word 按实际结构保护排版,不依赖文件名或报告内容。普通正文保留字体、分栏、表格边界并随文字流动;固定行距、固定行高等约束会在写回时处理。固定位置框中的长内容须通过渲染检查,可能发生重叠或无法验证时,保留待处理卡片和原文档。
135
+ - 检测到可能重叠、裁切或无法确认安全排版时,先提示并保留待处理修订。用户可以点击“仍然接受并写入”,写入后卡片持续提醒从标题栏打开 Office 手动调整排版,保存后自动刷新预览。确认仅针对当前文档和这份修订;不创建编辑副本,也不迁移修订。
136
+
137
+ ### 整段修订、PPT 跳页与旧 Word(0.1.16)
138
+
139
+ - Word 跨段选区先核对全部来源,按顺序拼成完整原文,一次提交给模型,生成一份完整修订。不再逐片段调用、逐片段跳过“无变化”;只在整个结果与整个原文相同时显示无变化。模型选择提供第二份扩写时,每一份都是完整选区的完整候选。
140
+ - 接受时整体替换该选区,不按生成结果的字数拆回段落;保留选区外的前后文字、圆点、相邻单元格及未选段落。保留原物理段落身份和原生修订记录,预览忽略本次合并产生的已删除空段;撤回恢复完整原文件。引用后的自然语言修改也支持完整跨段选区。
141
+ - 当前只支持连续的正文或同一表格单元格内的跨段选区。跨未选中的正文、单元格或图片/链接/复杂域的合并写回会明确拒绝,避免丢内容。同一选区的候选不能批量同时接受。
142
+ - PPT 底部页号可以直接输入,按 Enter 或点“跳转”;只接受 1 至总页数的整数,Esc 恢复当前页号。上下页同步页号,重新进入插件恢复阅读页,文件刷新后页数缩小时自动限制到有效页。
143
+ - 支持旧 `.doc`:导入时通过 DSH 的 Office 引擎转换成 `.docx` 并保存可修订副本,同名文件自动避让;外部原始 `.doc` 保留。已有书架目录中的 `.doc` 可阅读、选中引用及对话,点击“转换并编辑”创建并打开可修订的 DOCX 副本;旧 DOC 二进制文件不直接写回。转换失败显示原因且回滚本次导入,缺少 Office 引擎时提示安装组件。
144
+
145
+ ### 图片文档与选区修复(0.1.15)
146
+
147
+ - 发送及接受按钮使用 DSH 的主按钮背景、前景和悬停颜色,明暗主题切换即刻生效。
148
+ - 图片型 PPTX 封面和页面优先读取完整原图,不再为首页转换整册;复杂页面仍走版式转换。封面加载时先显示标题占位,文档保存后封面缓存自动更新。
149
+ - Windows 接入系统 WinRT OCR;缺少中文识别组件时显示安装提示。macOS 使用系统 Vision,无需 Xcode/Swift 编译环境。复杂幻灯片将原生文字与图片 OCR 合并,保留真实文字位置。
150
+ - 图片型 PPTX、PDF 的文档提问逐页收集 OCR/原生文字;所选模型在 DSH 中标明支持图片且附件服务可用时,通过 DSH 图片附件读取未识别页面,并把相关页原图附到提问中。图片识别、问答和修订使用所选模型,不自动换模型。
151
+ - 对话先显示问题,再显示「正在读取图片页 x / 总页数」动画。逐页记录缓存按文档内容及模型区分;文件变化后重新读取。一次最多读取 160 页;无法识别的页面和预算省略的内容明确告诉模型,避免把局部内容当成全文。
152
+ - 「东方证券」这类按视觉行拆成 Word 段落的双栏报告,可精确匹配圆点后的正文与重复片段;跨段改写保留完整选区作上下文,圆点仅保留、不单独扩写。仍逐段核对原文及版本,拒绝猜测写回位置。
153
+ - 选区末尾未包含句末标点时,润色、扩写和引用修改不额外补句末标点;保存修订前再检查尾部,避免接受后与选区外的句号重复。
154
+
155
+ ### 阅读与修订交互(0.1.16)
156
+
157
+ - 顶栏使用 DSH 的 `data-window-drag` 标记,参与宿主拖拽区域刷新;标题、文档名、格式徽章和中间空白区域明确设为拖拽区,按钮保持可点击。
158
+ - 修复预览滚动后顶栏空白处无法拖拽:正文及对话区域不再继承原生 `no-drag`,避免已经滚出视口的页面与控件覆盖顶栏的拖拽区域。标题及空白块单独参与宿主的区域刷新。
159
+ - Word 和有原生文字的 PDF 版式支持从空白处拖出矩形选框。框内选中的字会高亮,松手后可引用、复制或进行可用的文字操作;Word 的每个选区都核对源文字和位置,不连续的范围分别处理。
160
+ 普通拖选移到行外时不会缩回起始行;跨页拖选到上下边缘会自动滚动,完成拖选后的迟到滚动事件不会清掉菜单。拖选期间按 Esc 可以取消。
161
+ - 「清空输入」右侧的模型选择统一用于文档对话、引用修改、润色、扩写、翻译及重新生成;默认跟随 DSH,也可从已配置模型中选择并记住。一次请求及重试保持同一模型;重新生成使用当前选择,失败后的「重试」保留原请求的选择。所选模型不可用时明确提示重新选择,不转用默认模型。
162
+ - npm 作者字段为 `stone086`,通过当前 npm 登录用户确认。
163
+
164
+ - 引用对话明确将总结、概括和提炼要点作为回答;只有要求修改原文时才生成修订。完整回答放入 JSON 的 `reply`,换行与引号需正确转义。
165
+ 模型在 JSON 前后附加说明或代码围栏时,可提取唯一的完整决策对象;不会猜测缺失的修改文字或将普通文字当作修订。
166
+ 格式不完整、空回复或输出截断时自动重试一次,截断时增加输出预算。重试使用同一份问题、引用和位置,不重复保存问题或修订;两次失败后保留问题并提示重新发送。权限、版本变化、配额和取消请求不触发格式重试。
167
+ 对话记录增加诊断字段 `completion`,仅记录尝试次数、错误类别、结束状态与输出长度,便于排查;不额外保存失败的原始输出。
168
+ - AI 回复右下角显示复制图标与具体时间,悬停时间可查看完整日期。复制整条回复,成功后显示「已复制」;剪贴板权限不可用时尝试本地复制方式。当前 DSH 没有供插件调用的回复朗读接口,未显示朗读按钮。
169
+
170
+ - 修订卡片可以点击顶部箭头折叠和展开;折叠后显示结果摘要与状态。切换标签、刷新或重新进入插件时保留折叠状态。
171
+ - 去掉 Word 页面上「选中文字即可引用、润色、扩写或翻译;接受修订后写回 Word。」的说明及其占用的空白行。
172
+ - 文档标题右侧增加「用 Office 编辑」图标,打开书架内的原文件,可以手动修改。DSH 随附的 LibreOffice Kit 只有转换与预览能力,没有桌面编辑窗口;因此调用本机已安装的 Microsoft Office、完整版 LibreOffice、WPS 或 ONLYOFFICE。未找到编辑器时显示安装指引。
173
+ 保存同一个原文件后,插件确认文件变化稳定,再自动重新读取正文、版式预览和修订;保留对话草稿与卡片折叠状态。检查间隔约 1.5 秒,实际刷新还需等待解析和预览转换。
174
+ 在 AI 生成或写回期间暂缓刷新,完成后继续检测。文档变化后,旧 Word 修订不能按旧位置接受;另存为其他文件时需将新文件导入书架。
175
+
176
+ - 设置中的「改写」更名为「润色和扩写风格」。文风同时用于润色和扩写。
177
+ - 扩写支持「按增加比例」和「按目标字数」。默认增加约 100%,完整结果约为原文的 2 倍;例如增加 200% 表示结果约为原文的 3 倍。
178
+ 目标字数表示扩写后全文长度,需大于原文,可设 50–8000 字;增加比例可设 10%–500%。
179
+ 文风不再限制扩写幅度,即使选「简洁精炼」也会充分展开已有要点。自然语言中明确提出的字数或扩写程度优先于默认设置。
180
+
181
+ - 文档页合并为单行顶栏,文档名只显示一次,保留返回书架、面板折叠、新建书架和设置。
182
+ - 标签栏最右侧按当前标签显示「清空对话」或「接受全部」,与标签在同一排。
183
+ - 选区菜单「提问」改为「引用」。引用后可输入个性化修改要求,由模型判断是回答问题还是生成修订。
184
+ 生成修订后对话中提供「查看修订」入口;接受后才写回文件。可继续对话调整上一份草稿。
185
+ 生成前和生成完成后都核对引用原文与文档版本;不一致时提示重新引用。普通咨询和翻译不生成修订,无变化时直接说明。
186
+ - 在文档空白处右键选择「刷新文档」,重新读取正文、版式预览和修订记录;选中文字的右键菜单仍提供选区操作。
187
+
188
+ - 修订卡片增加「删除」,待处理、已撤回、已接受的卡片都可删除,刷新后保持隐藏。
189
+ 删除已接受的卡片会保留已写入文档的修改;需要还原文件时,先使用「撤回」。
190
+ - 文档对话支持 Markdown 标题、粗体、列表、引用、代码块、链接和表格。
191
+ - 「引用」先把选区放入输入区,保留已写的问题,用户编辑后点击「发送」。
192
+ 可以单独移除引用。「翻译」直接发送,保留输入框里尚未发送的问题;移除「解释」「重写」。
193
+ - 润色、扩写和翻译使用 DSH 对话原版鲸鱼尾巴动画资源,并显示处理状态;减少动态效果或强制颜色模式下显示静态尾巴。
194
+ - 点击「重新生成」后立即移除当前卡片,再显示生成动画。旧卡片刷新后仍保持删除;删除失败时恢复卡片,生成失败时可使用保存的原文与位置重试。
195
+ - 请求提交时保存独立的原文、文档版本和选区位置。等待期间点击空白处、取消高亮或选择其他文字不会改变请求;切换文档后迟到的结果不会混入新文档。
196
+ - 润色和扩写卡片只显示词级差异和操作按钮。未接受时显示「接受」,接受后显示「撤回」;接受按钮悬停时保持清晰的文字对比度。
197
+ - 润色、扩写结果与原文一致时,直接显示「内容无变化」,不创建修订卡片。两份结果中若只有一份有变化,只保留有变化的那一份。
198
+ - 扩写通常生成一份,由模型判断是否存在另一种有实质差异的扩写方向。只有有必要时才生成第二份。同一句话的待选扩写左右并排,供用户选择。
199
+ - 修订栏默认与文档对话同宽。只有存在两份可比较的待选结果时才自动加宽,并可拖动边界调整;接受或删除其中一份后自动恢复原有宽度,历史卡片改为纵向排列。
200
+ - 切换到其他插件再回来,恢复当前文档、阅读位置、右侧标签和修订栏宽度。
201
+ - 选中文字后即使浮动菜单消失,右键仍可重新打开同一组选区操作。
202
+ - 点击发送后立即显示问题和引文,再显示「思考中」;失败时保留问题和引用供重新编辑。
203
+
204
+ 更新安装包后请**完全退出 DSH 再重新打开**,macOS 使用 `⌘Q`;仅关闭窗口可能仍在运行旧版。
205
+ 可在插件设置 → 关于确认运行版本为 `0.1.18`。
206
+
207
+ ### Word 选区完整性(0.1.5)
208
+
209
+ Word 版式拖选使用 PDF 的真实字形宽度和逐字符位置,替代按字体类型估算宽度的透明文字层选区。
210
+ 高亮、引用与生成修订共用同一份精确原文,保留句尾;表格拖选限制在起始单元格,避免带上相邻格的内容。
211
+ 表格中的多段内容分别保存 Word 段落及段内位置,重复文字也能写入选中的单元格。
212
+ 生成前核对选区原文和文档版本,生成期间或接受前文档已变化时拒绝写入。
213
+ 旧版尚未接受的 Word 修订可能已有漏字选区,升级后需重新选中完整文字生成修订;已接受修订仍可撤回。
214
+
215
+ ### Word 版式选句改写(0.1.4)
216
+
217
+ Word 版式视图优先使用转换后 PDF 的真实文字层,仅没有文字层的页面使用 OCR。
218
+ 版式显示修改后的当前正文,转换时使用临时副本排除已删除的旧文字;源 Word 文件仍保留原生修订记录。
219
+ 升级后旧的 Word 预览和封面缓存会自动失效,连续改写不会再被旧修订文字干扰。
220
+ Word、PPT、PDF 只显示版式,Excel 保留「版式 / 文本」切换。
221
+ Word 移除「原文」入口,润色、扩写始终留在版式;无法定位时在当前页面提示重新选择。
222
+ 版式文字结合全文阅读顺序及相邻行的精确上下文对回 `.docx` 正文,区分重复句子,
223
+ 容许空格、换行及不可见换行符差异,保留逐字符位置。自动编号映射到正文后面的文字,
224
+ 不会把编号一起替换。跨段选区按段生成修订。文字层不完整且没有足够上下文时仍拒绝猜测位置。
225
+
226
+ Word 修订保留段落及段内选区位置,同一段中重复文字可准确修改选中的一处。
227
+ 写回前再次核对该位置的原文;位置失效会拒绝写入。同段批量修订从后往前应用,
228
+ 避免先写入的文字长度变化影响后面的选区。内置 LibreOffice Kit 用于转换和版式预览,
229
+ 插件本身通过 OOXML 写回 Word,不能据此视为完整的嵌入式 Word 编辑器。
230
+
231
+ ### 新机器与预览组件(0.1.1)
232
+
233
+ 插件优先复用 DSH 随附的 LibreOffice Kit 和 Python,不把大型引擎打进插件安装包。
234
+ 运行路径从当前 DSH 进程、应用安装位置和当前用户的 `DSH_HOME` / `~/.dsh` 自动查找,
235
+ 支持移动应用、不同用户名,以及 Windows 的 Node/Python 可执行文件布局。
236
+
237
+ 推荐安装或更新[官方完整 DSH 桌面版](https://www.deepseek.com/download/),然后完全退出并重启。
238
+ 独立安装 LibreOffice 桌面软件不会自动接入这个插件。
239
+ 若版式预览组件缺失,Word/Excel 的预览页和 PPT 错误提示会提供「查看安装指引」;
240
+ 设置 → 关于也提供同一入口。已导入的文件会保留,无需重新导入。
241
+
242
+ 命令行或第三方 DSH 若没有携带引擎,可按安装指引使用 npm 将
243
+ `@deepseek-ai/libreoffice-kit@0.1.2`(包括 optional 引擎包)安装到
244
+ `$DSH_HOME/doc-assistant/preview-runtime`,安装后重启 DSH,插件会自动查找它。
245
+ 需要 Node.js ≥ 22.19。引擎的下载大小取决于系统,可能需要数百 MB。
246
+ Office 正文提取和修订写回还依赖 DSH 自带 Python 及文档库。
247
+
248
+ 自定义环境仍可通过 `DSH_DOC_LIBREOFFICE_CLI`、`DSH_DOC_NODE`、`DSH_DOC_PYTHON`
249
+ 指定组件路径。导入时会显示旋转动画、当前文件、文件序号和处理阶段,
250
+ 封面准备期间提示持续显示;成功、部分成功或失败后会在书架显示结果。
251
+
252
+ ### 源码安装
253
+
254
+ 插件源码在本仓库,通过软链进入 DSH profile:
255
+
256
+ ```bash
257
+ PROFILE=~/.dsh/profiles/desktop
258
+ ln -sfn /Users/stone/Desktop/ceshi/dsh-doc-assistant "$PROFILE/node_modules/dsh-doc-assistant"
259
+ ```
260
+
261
+ 然后在 `$PROFILE/cordis.patch.yml` 的 `- insert:` 列表里加一行:
262
+
263
+ ```yaml
264
+ - id: dsh-doc-assistant
265
+ name: "dsh-doc-assistant"
266
+ ```
267
+
268
+ 这一行做两件事:应用宿主半(注册 `doc_*` 工具 + `/doc-assistant` 路由),
269
+ 并让 `dsh-client-modules` 扫描到本包,把 `lib/client.js` 送到 Web GUI。
270
+
271
+ 改动源码后自动热重载,把源码目录加进 HMR watch root:
272
+
273
+ ```yaml
274
+ - id: hmr
275
+ disabled: false
276
+ config:
277
+ root:
278
+ - /Users/stone/Desktop/ceshi/dsh-doc-assistant
279
+ ```
280
+
281
+ > **新增 client 插件不是 HMR 能就地替换的改动** —— 装好后必须刷新一次 Web GUI。
282
+ > 之后改宿主半会热重载;改客户端半要重跑 `node dev/build-client.mjs` 再刷新页面
283
+ > (除非 `pnpm run dev:web` 在跑)。
284
+
285
+ ### 卸载
286
+
287
+ ```bash
288
+ PROFILE=~/.dsh/profiles/desktop
289
+ rm "$PROFILE/node_modules/dsh-doc-assistant"
290
+ # 再从 cordis.patch.yml 删掉对应行与 hmr root
291
+ ```
292
+
293
+ ---
294
+
295
+ ## 使用
296
+
297
+ **入口**:侧边栏「**企业文档助手**」图标 —— 打开的是**书架**。
298
+
299
+ ### 书架(总览)
300
+
301
+ 每个项目是一个**独立的架**:架头显示项目名与文档数,下面是横向排列的书卡。
302
+
303
+ **封面优先用文档自己的首页**(阅读类软件的做法):
304
+
305
+ | 格式 | 封面 |
306
+ |---|---|
307
+ | 图片 | 图片本身 |
308
+ | PDF | 第 1 页 |
309
+ | Word / PPT / Excel | **转 PDF 后取第 1 页** |
310
+ | Markdown / 文本 / 代码 | 自动生成(渐变 + 书脊 + 标题排版) |
311
+
312
+ **书卡形状跟随文档自身宽高比** —— 16:9 的幻灯片是横版卡、A4 文档是竖版卡,
313
+ 所以 PPT 首页不会被裁掉标题,混排起来像真书架。
314
+
315
+ - **点书** → 进入阅读器;顶栏出现「← 返回书架」
316
+ - **+ 新建书架** → 顶栏右上角,新建一个书架(用**系统目录选择器**挑根目录)
317
+ - **架内 + 添加文档** → 从本机选文件,复制进该书架(重名自动避让成 `报告 (2).md`)
318
+ - **右上角 ⚙** → 打开**设置窗口**
319
+ - 封面**全自动**:上传后自动生成,打开书架时按需渲染;有缓存后是毫秒级
320
+
321
+ ### 阅读器
322
+
323
+ 左栏是 **项目 → 大纲 → 文件目录**(阅读时大纲排在最前)/ 中正文 / 右对话,三栏一屏。
324
+ 两侧各有一个**收起/展开按钮**(样式与 DSH 自身一致)。
325
+
326
+ 桌面版可拖动单行顶栏的标题及空白处来移动整个 DSH 窗口。
327
+ 拖拽区至少 44px 高,Mac 侧栏折叠时为窗口控件留出空间;返回、设置等按钮仍正常响应点击。
328
+
329
+ **引用与对话**:正文里选中文字 → 浮出工具条 →「引用」把选中内容作为**引文**
330
+ 放到右侧输入区 → 输入问题或修改要求 → 点击「发送」。发送后先显示问题和引文,再显示「思考中」。
331
+ 模型区分咨询与修改要求:咨询直接回答,修改生成待接受的修订,可点击「查看修订」。
332
+ 可继续对话调整上一份草稿;移除引用或清空输入会停止沿用旧的引用位置。
333
+ 回答支持 Markdown 排版。对话是**每份文档各自的历史**,切换文档时自动切换,改写文档后历史仍在。
334
+ 「翻译」直接将选区送到文档对话,立即显示引文与问题,再显示翻译中的动画。
335
+
336
+ 选区工具条按阅读区与可视窗口的边界定位。靠近边缘时自动移回区域内,窄窗口按需换行,高度不足时可在菜单内滚动。
337
+
338
+ 保留选区时,右键也能打开同一菜单。
339
+
340
+ **改**:选中文字点「润色」或「扩写」→ 右栏「修订」标签出现词级差异卡片
341
+ (删去文字红底删除线、增加文字绿底下划线)→ 未接受时点击「接受」,写入后点击「撤回」还原。
342
+ 也可以批量接受互不冲突的修订;同一句话存在多份扩写时需选择其中一份。
343
+ 卡片上的「删除」只清理卡片;删除已接受的卡片不会撤销文档中的修改。
344
+ 点击卡片顶部箭头可折叠结果,展开后恢复差异与操作按钮。
345
+
346
+ 标题旁的编辑图标可用本机 Office 打开当前文件。手动修改并保存原文件后自动刷新预览;没有桌面编辑器时,按页面安装指引安装后再点击图标。
347
+
348
+ 普通咨询直接回答;带原文引用的修改要求可生成修订,仍需点击「接受」才写回。
349
+
350
+ ### 设置窗口
351
+
352
+ 右上角齿轮打开的**独立窗口**(可拖动标题栏,Esc / 点遮罩 / 关闭按钮三种关法),
353
+ 左侧分区导航:
354
+
355
+ | 分区 | 内容 |
356
+ |---|---|
357
+ | 项目 | 项目 CRUD、多根目录(路径 / 标签 / 只读开关) |
358
+ | 封面 | 是否自动生成、送给模型的文档长度、「重建封面缓存」 |
359
+ | 对话 | 历史上限、随文档附带的正文长度、携带轮数 |
360
+ | 改写 | 风格预设、上下文长度、快照保留数 |
361
+ | 关于 | 版本与数据目录 |
362
+
363
+ > 「重建封面缓存」是**维护动作**(清掉缓存让它们自动重生成),不是"手动生成封面"——
364
+ > 封面本来就是全自动的。
365
+
366
+ ---
367
+
368
+ ## 数据存放
369
+
370
+ | 路径 | 内容 | 权限 |
371
+ |---|---|---|
372
+ | `$DSH_HOME/doc-assistant/config.json` | 插件设置 | 600 |
373
+ | `$DSH_HOME/doc-assistant/projects.json` | 项目注册表 | 600 |
374
+ | `$DSH_HOME/doc-assistant/revisions/<projectId>/<docHash>.json` | 未处理与历史修订 | 600 |
375
+ | `$DSH_HOME/doc-assistant/history/<projectId>/<时间戳>-<文件名>` | 每次落盘前的原文件快照 | 600 |
376
+
377
+ `$DSH_HOME` 默认 `~/.dsh`。
378
+
379
+ ---
380
+
381
+ ## 开发
382
+
383
+ ```bash
384
+ node dev/build-client.mjs # 从 src/client/*.js 生成 lib/client.js(必须跑!)
385
+ node dev/build-client.mjs --check # CI 用:产物是否最新
386
+ node dev/harness.mjs # 宿主半测试
387
+ node --test dev/review-regression.mjs # 并发写回 / 整组撤回 / 上传占位回归
388
+ node dev/render-test.mjs # 客户端半测试
389
+ npm run test:ui # 选区菜单边界 / 缩放 / 交互回归及客户端端到端检查
390
+ node dev/spike-client-view.mjs # M0 门禁:conversation.view 注册契约
391
+ ```
392
+
393
+ ### 客户端半为什么需要构建
394
+
395
+ DSH 的客户端模块系统每个包只服务**一个**浏览器产物,而客户端半只能 `require()` 平台种子表
396
+ (React 等),拿不到任何 npm 包。所以本包把客户端源码拆成 `src/client/*.js`(一人一档,不冲突),
397
+ 由 `dev/build-client.mjs` 拼成单个 lazy-CJS bundle,并加一个七行的模块注册表,
398
+ 让这些文件之间还能 `require('./dom')` 互相引用。
399
+
400
+ **零依赖、零转译、无 JSX。** 构建脚本会校验每个文件的 `__define('<id>', ...)` 声明与文件名一致,
401
+ 并用 `vm.Script` 做语法解析——这两道关卡拦住的是"构建成功但产物是坏的"那类事故。
402
+
403
+ ### 加一个客户端模块
404
+
405
+ 1. 新建 `src/client/<序号>-<名字>.js`
406
+ 2. **第一条语句**写 `__define('./<名字>', (module, exports, require) => {`
407
+ 3. 只 `require('react')` 与 `./` 开头的本包模块
408
+ 4. 重跑 `node dev/build-client.mjs`
409
+
410
+ ### 关键约束(踩了就崩)
411
+
412
+ | 约束 | 说明 |
413
+ |---|---|
414
+ | `host.call()` **不可用** | 那是动态包(`cordis_run`)专用。文件型插件一律 `fetch('/doc-assistant/...')` |
415
+ | `styles.insert()` **不可用** | 同上。用 `document.createElement('style')` |
416
+ | 不能 `require` npm 包 | 只能用平台种子表 + 本包模块 |
417
+ | 宿主半不能 `import '@deepseek-ai/*'` | 插件被软链进 profile,裸标识符解析不到 |
418
+ | 文档写回必须先备份 | `accept` 流水线:校验 hash → 备份 → apply → verify → 原子写 |
419
+
420
+ ---
421
+
422
+ ## 文档
423
+
424
+ | 文件 | 内容 |
425
+ |---|---|
426
+ | [`CONTRACT.md`](CONTRACT.md) | **接口冻结文档**:IPC 路由、数据形状、模块边界、集成裁决 |
427
+ | [`docs/SLOT-CATALOG.md`](docs/SLOT-CATALOG.md) | 从 DSH 应用包抽出的 90 个插槽完整目录(ownerProps / standardProps / 注册示例 / 源码路径) |
428
+
429
+ ---
430
+
431
+ ## 已知限制与后续
432
+
433
+ - **M1 范围**:文本类格式(`.md`/`.txt`/`.html`/代码)的完整闭环 + 项目管理 + 对话
434
+ - **M2 计划**:`.docx`(OOXML 原生 `w:ins`/`w:del`)、`.xlsx`、`.pptx` 三种 Writer;PDF 只读预览;书签与高亮
435
+ - **M3 计划**:全文检索、审计日志、文档状态流转、团队共享
436
+ - 同一物理文件的 `accept` / `restore` / `reject` 已按 canonical 路径串行;批量接受共用一次快照,单条撤回会拒绝并要求整组还原
437
+ - 模型工具 `doc_apply_revision` 与面板共用写回逻辑、文件锁、只读及版本检查;旧记录缺少写后指纹时拒绝自动撤销,以免覆盖后续编辑
438
+ - 上传使用硬链接原子发布;不支持硬链接的文件系统会拒绝上传,请选择支持的目录
439
+ - 图片 OCR 旁注、跨文档引用均未实现
440
+
441
+ ---
442
+
443
+ ## 许可
444
+
445
+ MIT。
@@ -0,0 +1,15 @@
1
+ # Bundle patch for the dsh-doc-assistant plugin.
2
+ #
3
+ # Inserting one Loader row does two things at once:
4
+ # 1. the host half (lib/index.js) is applied, registering the doc_* tools and
5
+ # the /doc-assistant HTTP routes;
6
+ # 2. the row makes the package visible to the dsh-client-modules scan, which
7
+ # serves the `dsh.client` bundle (lib/client.js) to the Web GUI.
8
+ #
9
+ # No `config:` is declared here on purpose: the plugin reads its own
10
+ # config.json (created on first run under $DSH_HOME/doc-assistant/) and adding a
11
+ # row config would silently outrank that file. Add a `config:` block only if you
12
+ # want to pin settings in the profile.
13
+ - insert:
14
+ - id: dsh-doc-assistant
15
+ name: 'dsh-doc-assistant'