dsh-input-assistant 0.0.0-stage → 0.1.4

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 (44) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/LICENSE +21 -0
  3. package/README.en.md +100 -0
  4. package/README.md +215 -3
  5. package/cordis.patch.yml +3 -0
  6. package/docs/CHANGELOG-0.1.2.md +102 -0
  7. package/docs/evaluation.md +111 -0
  8. package/docs/images/dark.png +0 -0
  9. package/docs/images/light.png +0 -0
  10. package/docs/images/optimize.png +0 -0
  11. package/docs/references.md +39 -0
  12. package/docs/smoke-comparison.md +37 -0
  13. package/docs/validation.md +180 -0
  14. package/lib/browser/components.d.ts +11 -0
  15. package/lib/browser/controller.d.ts +187 -0
  16. package/lib/browser/dom.d.ts +29 -0
  17. package/lib/browser/floating.d.ts +21 -0
  18. package/lib/browser/index.d.ts +6 -0
  19. package/lib/browser/public.d.ts +2 -0
  20. package/lib/browser/runtime.d.ts +55 -0
  21. package/lib/browser/settings.d.ts +8 -0
  22. package/lib/browser/styles.d.ts +1 -0
  23. package/lib/client.js +2646 -0
  24. package/lib/client.meta.json +274 -0
  25. package/lib/core/config.d.ts +17 -0
  26. package/lib/core/context.d.ts +4 -0
  27. package/lib/core/diff.d.ts +6 -0
  28. package/lib/core/generation.d.ts +15 -0
  29. package/lib/core/index.d.ts +9 -0
  30. package/lib/core/models.d.ts +15 -0
  31. package/lib/core/protection.d.ts +18 -0
  32. package/lib/core/scheduler.d.ts +10 -0
  33. package/lib/core/snapshot.d.ts +2 -0
  34. package/lib/core/types.d.ts +92 -0
  35. package/lib/core.js +750 -0
  36. package/lib/core.js.map +7 -0
  37. package/lib/host/rpc.d.ts +31 -0
  38. package/lib/host/runtime.d.ts +28 -0
  39. package/lib/host/storage.d.ts +62 -0
  40. package/lib/host/transcript.d.ts +19 -0
  41. package/lib/index.d.ts +66 -0
  42. package/lib/index.js +1164 -0
  43. package/lib/index.js.map +7 -0
  44. package/package.json +128 -3
Binary file
Binary file
@@ -0,0 +1,39 @@
1
+ # 公开实现对照与来源
2
+
3
+ 记录日期:2026 年 10 月 22 日。这里比较的是所列公开文档和指定插件版本,不是对所有产品功能的穷尽盘点。
4
+
5
+ ## 能力与本插件的定位
6
+
7
+ | 公开参考 | 本次核实的能力 | 本插件采用的方向与区别 |
8
+ |---|---|---|
9
+ | PI 的 `pi-prompt-enhancement` | 独立模型请求改写草稿,一键回填,强调保留意图、语言和标识符 | 保留一键操作,另加当前会话上下文、选区处理、原文保护和差异还原;不复制其源代码或提示词 |
10
+ | Claude Code Prompt suggestions | 回复后根据会话,用相同模型作后台请求,建议可采纳为草稿 | 参考下一句建议的交互;本插件通过 DSH 已配置的模型独立生成 |
11
+ | Codex Composer Predictions | 根据当前会话建议下一条消息,Tab 采纳为可编辑草稿 | 参考采纳后可编辑、由用户发送的流程;不依赖 Codex 内部预测服务 |
12
+ | `studyzy/dsh-suggest-prompt` | DSH 回合后生成一句用户口吻建议,宿主存储及输入框灰字 | 参考公开接口使用方式;本插件把下一句和输入中续写纳入一个调度器,并允许有依据的追问和纠偏 |
13
+ | `fishcg/dsh-input-prediction` | DSH 输入续写及回复后候选建议 | 参考两种模式的使用场景;本插件采纳只写草稿,并共用优化、保护和版本守卫 |
14
+ | 本插件 | 优化、下一句、续写、当前会话草稿暂存 | 以同一输入流程解决组织表达、检查改动和保存长草稿的问题;质量仍需独立评测 |
15
+
16
+ 这些差异是可检查的功能或策略差异,不等于准确率排名。比如更长历史和允许追问能覆盖更多场景,也可能引入额外噪声;必须把可用率、弃权率、错误新增要求和延迟一起评估。
17
+
18
+ ## 公开源码与许可
19
+
20
+ - **本项目**:独立实现的源代码按 MIT 发布,见根目录 `LICENSE`。
21
+ - **PI 参考插件**:已核对 [`f04349ae...` 的 LICENSE](https://github.com/vastsa/pi-prompt-enhancement/blob/f04349ae6902d0d6be880cc19b20e68942d78721/LICENSE),使用 LGPL-3.0。其代码、原始提示词和构建产物未拷入本发行包,也不作为运行依赖。我们参考的是用户操作流程,实际提示词和实现另行编写。
22
+ - **DSH SDK**:通过官方已发布 SDK 的扩展接口集成,目标为 `0.2.1-rc.2`;运行时共享的 SDK、Cordis、React 保持外部引用。依赖仍适用其各自许可证,不能把本项目的 MIT 解释为替依赖重新授权。
23
+ - **社区参考插件**:`studyzy/dsh-suggest-prompt` 和 `fishcg/dsh-input-prediction` 的许可证均已核对为 MIT。它们是调研参考,不是本包依赖;本包不包含其插件构建产物。
24
+ - **Claude Code**:公开仓库的 [LICENSE.md](https://github.com/anthropics/claude-code/blob/main/LICENSE.md) 使用商业条款。仓库可访问不等于完整实现可按开源许可证移植。本项目没有复制其内部实现。
25
+ - **Codex**:公开 CLI、app-server 等组件的许可与桌面端预测功能的公开范围应分开判断。本项目不连接或复制其内部预测服务。
26
+
27
+ Claude Code 文档公开了后台请求、会话缓存及采纳行为;Codex 文档公开了基于当前会话的预测与 Tab 采纳行为。**本项目未取得这两款产品的完整内部预测提示词或生成链路。** 自行编写的提示词不应标注为官方原版,也不能承诺复现或超越其预测效果。
28
+
29
+ ## 精确参考
30
+
31
+ - [DSH bundle 打包与安装说明](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/docs/user/develop/basic/publish.md)
32
+ - [DSH `0.2.1-rc.2` conversation 发布包元数据](https://registry.npmjs.org/@deepseek-ai%2Fdsh-client-ui-conversation/0.2.1-rc.2)
33
+ - [DSH 输入动作契约](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/client/ui-conversation/src/client/contract/input.ts)
34
+ - [DSH 原生键盘仲裁](https://github.com/deepseek-ai/deepseek-harness/blob/687f282e8625c6b8d11ff58211a90524be2e4317/packages/client/ui-conversation/src/client/input/editor/keymap.ts)
35
+ - [PI 提示词增强参考实现](https://github.com/vastsa/pi-prompt-enhancement/blob/f04349ae6902d0d6be880cc19b20e68942d78721/main.js)
36
+ - [Claude Code Prompt suggestions](https://code.claude.com/docs/en/interactive-mode#prompt-suggestions)
37
+ - [Codex Composer Predictions](https://learn.chatgpt.com/docs/features/composer-predictions)
38
+ - [studyzy 建议生成参考实现](https://github.com/studyzy/dsh-suggest-prompt/blob/b02261d6a51bad0cd8c832b13d9def9e1e7b149e/src/generate.ts)及其 [MIT 许可](https://github.com/studyzy/dsh-suggest-prompt/blob/b02261d6a51bad0cd8c832b13d9def9e1e7b149e/LICENSE)
39
+ - [fishcg 输入预测参考实现](https://github.com/fishcg/dsh-input-prediction)及其 [MIT 许可](https://github.com/fishcg/dsh-input-prediction/blob/main/LICENSE)
@@ -0,0 +1,37 @@
1
+ # 低用量真实模型试验
2
+
3
+ 日期:2026 年 10 月 22 日。此试验用于检查真实模型接线和观察少量输出,不是完整质量验收。
4
+
5
+ ## 方法和用量
6
+
7
+ 在当前官方 DSH Windows `0.2.1-rc.2` 宿主中,通过已有 `ctx.llm` 连接串行执行 6 次辅助请求。路线为 `deepseek-account / deepseek-flash`,目录显示 DeepSeek-V4.1-Flash;界面模型标记为 1017。六次均显式选择模型声明的最低推理档 `off`、temperature 0、输出上限 256 tokens,不自动重试,不创建 Agent,不写主会话事件。
8
+
9
+ 三个操作各选一个合成案例,并与一个公开实现的提示词比较。候选使用实际已安装插件的提示词构造和输出校验。基线原提示词仅保存在不随发行分发的研究目录,通过同一模型请求;没有安装或执行基线插件,因此没有比较其完整 UI、调度或后处理。
10
+
11
+ 此次模型试验发生在新增设置页及三级优化强度之前;候选核心 SHA-256 为 `02667fa4afc0342806e1aca3ecb33607276a430c8c523f26695c597ce08c3dd0`。最终版本的新强度策略只做了结构与保护回归,未逐档追加真实模型测量;本表不能作为三级强度效果的验收结果。
12
+
13
+ 提供商记录的六次用量合计:输入 **2,706 tokens**(其中缓存读取 256)、输出 **101 tokens**,总计 **2,807 tokens**。另有一次通过实际桌面按钮发起的短草稿优化,已成功回填,但未单独采集其 token 用量;因此不能把 2,807 表述为本次所有操作的精确总用量。其余自动化、宿主和 UI 夹具均不调用付费模型。
14
+
15
+ ## 观察
16
+
17
+ | 操作 | 合成场景 | 候选观察 | 基线观察 | 单次耗时,候选 / 基线 |
18
+ |---|---|---|---|---|
19
+ | 优化 | 简短、已经清晰的解释要求,禁止改文件或加功能,保护一个路径 | 保持原稿;路径占位映射完整恢复 | PI 调整措辞,保留约束和路径 | 626 / 1,075 ms |
20
+ | 下一句 | 用户要求解释两个概念,助手只解释了一个 | 建议继续询问尚未解释的概念 | studyzy 同样建议继续解释该概念 | 772 / 786 ms |
21
+ | 续写 | 已有前缀请求解释缓存失效 | 返回可直接追加的短后缀 | fishcg 返回可直接追加的较短后缀 | 578 / 862 ms |
22
+
23
+ 基线版本及研究适配:
24
+
25
+ - [PI `f04349ae…`](https://github.com/vastsa/pi-prompt-enhancement/blob/f04349ae6902d0d6be880cc19b20e68942d78721/main.js):沿用其不带会话历史的优化流程;研究提示词没有纳入 MIT 发行包。
26
+ - [studyzy `b02261d6…`](https://github.com/studyzy/dsh-suggest-prompt/blob/b02261d6a51bad0cd8c832b13d9def9e1e7b149e/src/generate.ts):使用其默认系统提示词和本案例最近一轮交流。
27
+ - [fishcg `8145b9cf…`](https://github.com/fishcg/dsh-input-prediction/blob/8145b9cf33e07207f186029341e0b6b25eb1012e/lib/index.js):静态提取时风格区标题缺少括号内的语气提示,其余系统与续写指令保留。该处适配存在偏差,不能作为严格等价竞品测量;保留结果并修正构造器,没有为此额外重跑。
28
+
29
+ 原始安全报告保留在开发工作区的临时证据目录(`.test-runtime/benchmark/`,已被 `.gitignore` 排除,不随仓库或安装包分发),其中含提示词版本、输出、结束原因、用量和耗时。研究材料不随安装包分发。
30
+
31
+ ## 能说明什么
32
+
33
+ 这三个案例中的候选输出符合基本操作要求,实际模型调用链能够工作。优化案例原稿已经清晰,保持原文也符合本插件策略;不能把“改写更多”直接算作优化更好。
34
+
35
+ **当前不能证明模型效果处于同类领先地位。** 每种操作只有一个案例,未覆盖歧义弃权、纠偏、长历史和多语言;下一句案例还与提示词示例相近,存在明显有利偏差。单次延迟也受缓存、网络和顺序影响。没有进行匿名多人语义评分,没有调用 Claude/Codex 的内部预测链路,也没有完成 60 条固定评测。
36
+
37
+ 工程上可以核实的优势是功能整合、版本校验、保护片段、原生撤销和暂存恢复;这些提高可控性,不能代替意图符合率的证据。完整质量状态继续保持 `not_evaluated`,详见 [评测流程](evaluation.md) 和 [验收记录](validation.md)。
@@ -0,0 +1,180 @@
1
+ # 验收记录
2
+
3
+ 此文件记录实际执行证据,不把发布接口核对、模拟模型测试或参考答案当作真实模型验收。
4
+
5
+ ## 2026-11-10:0.1.4 发布准备复验(未发布)
6
+
7
+ 按照版本整理要求,将下方内部 0.1.6 的代码以 0.1.4 作为当前待发布版本;下方记录的内部版本号与哈希保留为历史事实。桌面上用户提供的原始同名 0.1.4 归档与本次重新构建的包内容不同。
8
+
9
+ Windows x64、Node 24.22.1 的完整工程测试为 **203/203**,无失败或跳过,包含正式包 Loader 和 Edge 主题。实际 0.1.4 包的 Edge 浏览器回归 **14/14**,使用真实归档 client/core、React、Lexical 和宿主主题,RPC 与模型输出为本地替身。类型检查、严格包消费者和两个负向控制通过;中英文 README 的本地链接均已核对。无需真实模型调用,模型质量、原生操作系统 IME、完整桌面及其他插件组合仍未验收。工作流已配置,远端 CI 尚未运行。
10
+
11
+ 记录位于本地忽略目录 `.test-runtime/verification-release-014-tests.txt`、`verification-release-014-packaged-web.txt` 与 `packaged-0.1.4/result.json`。这些文件不随安装包发布。`dist/` 仅保留本次构建的 0.1.4 归档。
12
+
13
+ ## 2026-11-10:内部 0.1.6 定制版整合与复验(历史记录,未发布)
14
+
15
+ 本轮以用户提供的 `dsh-input-assistant-0.1.4.tgz` 为审阅对象,其 SHA256 为 `fc89fb5bd8508c08c1d2c68f8bf66ebc5a43d6d3d03e62cec2ebd0edbb6983f8`。该包与此前本地构建的同版本不同;先隔离复现,再将其新增功能整合到已修复的本地源码,保留 core/host/browser 分层,形成 0.1.6。原始归档未修改。
16
+
17
+ | 检查 | 本轮实际结果 |
18
+ |---|---|
19
+ | 全量工程测试 | Windows x64、Node 24.22.1:13 个文件、203 个测试通过,0 失败、0 跳过;含正式 `.tgz` 官方 Loader 与真实 Edge 主题测试 |
20
+ | 最低 Node 版本 | 便携 Node 22.19.0:12 个文件、198 个非 Edge 测试通过;类型检查、严格安装包消费者通过;系统 Node 未修改 |
21
+ | 源码浏览器回归 | 真实 Edge、React、Lexical、生产组件及宿主主题,15 个场景通过,正常退出 |
22
+ | 安装包浏览器回归 | `pnpm test:package:web` 直接服务归档中未经改写的 `client.js`、`core.js`,夹具不得导入 `src/`;14 个场景通过,0 浏览器异常 |
23
+ | 安装包与类型 | 实际包宿主导入、浏览器 factory、独立消费者解析通过;core 和主入口在 Bundler/NodeNext/Node16 下均 strict、skipLibCheck=false;移除映射或声明的两个负向控制均确实失败 |
24
+ | 正式宿主链路 | 官方 Loader/Gateway 验证配置、固定辅助模型实际 dispatch、主会话路由保持、卸载重载保留设置;首次 storage.open 失败恢复及跨客户端设置取消另有回归 |
25
+ | 新功能与并发 | 三档详略度、三种待保存预设、独立预测、手动重试、复制、取消清空、配置与路由变更隔离均通过;删除与撤销不出现误导的取消入口 |
26
+ | 独立核心复验 | 直接读取实际归档:8 组检查通过,含三档共 33 组显式长度边界、5 种清理后空输出、18 组异常代理字符、路径引号与多行/前导空白 |
27
+ | 构建及 CI | 全部 `lib/` 产物重复构建哈希一致;CI/发布 YAML 解析通过;Windows CI 增加实际包浏览器回归及全部构建产物比较;未运行远端 CI |
28
+ | 质量评测工具 | 60 条结构校验及当前提示词导出通过;真实模型调用 0 次;完整模型效果集仍为 `not_evaluated` |
29
+
30
+ 安装包浏览器场景覆盖预览/明确采纳/一次原生撤销、原文路径引号、键盘预览焦点及失效回收、编辑中断后的迟到候选隔离、取消清空、失败后明确重试、精确草稿复制、限流至少等待返回期限且仅重试一次、合成 IME 事件、后台抑制、Esc 与菜单焦点、详尽多行及超限拒绝、预设保存与 601ms 精确数值、辅助模型重读、窄屏深色菜单滚动。
31
+
32
+ 本轮还修正了两个真实浏览器问题:`transition: all` 延迟预览可见性而导致键盘聚焦失败;隐藏滑块的步长校验阻止合法的精确整数保存。最终界面截图已更新。发行包包含当前更新日志和 README 引用的截图。
33
+
34
+ 本地证据位于 `.test-runtime/verification-016-tests.txt`、`verification-016-node22-tests.txt`、`verification-016-node22-package.txt`、`verification-016-web.txt`、`verification-016-packaged-web.txt`、`verification-016-independent-core.json` 及 `packaged-0.1.6/result.json`。最终归档 SHA256 和全部构建产物校验记录另存 `verification-016-final.json`,避免将归档自身哈希嵌入归档造成循环。运行证据不随发行包上传;可用仓库脚本复现。
35
+
36
+ 浏览器测试的 RPC 和模型输出使用本地替身,复制测试验证 Clipboard API 的传入文本;实际宿主接线由独立的 Loader/Gateway 测试承担。本轮未改实时 DSH、未提交或发布。原生操作系统 IME、完整桌面组合、其他插件组合和真实模型语义效果未验证,不能由以上通过项推定。
37
+
38
+ ## 2026-11-09:0.1.5 二次修复及功能验证(未发布)
39
+
40
+ 保留 core/host/browser 分层,本节保留 0.1.5 当时的本地验证;上方为内部 0.1.6 的历史验证,后面的 0.1.4 与 2026-10 记录同样为历史证据。
41
+
42
+ | 检查 | 本轮实际结果 |
43
+ |---|---|
44
+ | 全量工程测试 | Node 24.22.1:13 个文件、177 个测试通过,0 失败、0 跳过,含实际 0.1.5 安装包的官方 Loader 与真实 Edge 主题 |
45
+ | 最低 Node 版本 | 官方便携 Node 22.19.0(Windows x64,官方 SHA256 已核对):12 个文件、172 个非 Edge 主题测试通过;类型检查与严格包消费者通过。系统 Node 未变更 |
46
+ | 真实 Edge 冒烟 | 11 项通过并正常退出,包含预览/采纳/原生撤销、Esc、暂存、Tab、菜单焦点、手动失败后重试、草稿复制、预览自动失效焦点、页面可见性和辅助模型选择 |
47
+ | 辅助模型目录 | 无会话只读加载;部分目录失败与不可用能力降级为手填;保留现有选择;实际 Edge 验证选择辅助模型不会改变主会话路由或触发生成 |
48
+ | 手动建议 | 自动功能关闭仍可明确请求、失败/弃权可重试,限流仅延后一次且不形成自动循环;忙碌、IME、附件/引用、过期快照及后台状态限制仍保留 |
49
+ | 撤销所有权 | 删除完成或尚在回包时切换会话仍能找回原 ID/时间;原 10 秒截止不延长;容量失败目标独立保留;二次冲突不静默覆盖两批备份 |
50
+ | 文本完整性 | 中文紧贴文件名/dotfile/路径的精确保护与篡改拒绝;Unicode 码点预算在核心、RPC 和暂存一致;编辑器偏移仍使用宿主单位 |
51
+ | 打包与类型 | 实际归档宿主导入和浏览器 factory 通过;strict、skipLibCheck=false 下 Bundler/NodeNext/Node16 ESM core 消费者全部通过 |
52
+ | CI 配置 | Linux Node 22.19/24.19 矩阵,版本 tag 仅经发布流程调用完整 CI;YAML 与依赖检查通过,本轮未执行远端 CI 或发布 |
53
+ | 评测工具 | 60 条结构校验及当前提示词导出通过,0 次真实模型调用 |
54
+
55
+ 保护扫描的 5 次预热、50 次重复本机测量:连续中文 4k/8k/16k/32k 平均约 0.187/0.333/0.660/1.289ms,保留线性增长趋势。这是合成输入测量,不能作为用户平均延迟或模型质量证据。
56
+
57
+ 本轮本地记录:`.test-runtime/verification-015-tests.txt`、`verification-015-node22-tests.txt`、`verification-015-web.txt`、`015-protection-benchmark.json` 和 `web/result.json`。这些记录位于忽略的运行目录,不随发行包上传。
58
+
59
+ 本轮未改实时 DSH 配置、未调用付费模型。60 条完整模型质量集仍为 `not_evaluated`;原生 IME 和完整其他插件组合仍需单独验证。中文文件名与紧贴自然语言存在歧义时,使用引号、反引号或手动锁定。
60
+
61
+ ## 2026-11-09:0.1.4 源码修复复验(未发布)
62
+
63
+ 本节为 0.1.4 源码修复时的本地验证,后面的 2026-10 记录保留为历史证据。环境为 Windows x64、Node.js 24.22.1、pnpm 11.25.0,使用现有锁文件。
64
+
65
+ | 检查 | 本轮结果 |
66
+ |---|---|
67
+ | 类型、构建与安装包 | `pnpm typecheck`、`pnpm build`、`pnpm pack --pack-destination dist`、`pnpm test:package` 通过;包校验包括实际归档宿主导入与严格 TypeScript core 消费者 |
68
+ | 全套工程测试 | `pnpm test`:12 个文件、153 个测试通过,0 失败、0 跳过;包含真实 `.tgz` 官方 Loader 与 Edge 主题测试 |
69
+ | 真实 Edge 编辑器回归 | `pnpm test:web`:6 项场景通过,覆盖预览保留原稿、明确采纳及原生一次撤销、Esc 放弃、显式还原、暂存恢复、灰字 Tab/Esc 与菜单焦点 |
70
+ | 新增底层回归 | 固定辅助路由保存后实际调用、首次存储打开失败恢复、预测失败/切模型重试、限流到期恢复与真正弃权缓存、路径/URL 保护、旧回包隔离、删除原子撤销 |
71
+ | UI 与设置 | 预览/取消、IME/原生菜单/已消费事件保护、菜单键盘焦点、灰字可访问提示、菜单关闭后的删除撤销、设置加载失败重试均有回归 |
72
+ | 评测工具 | 60 条结构校验和当前提示词导出通过;真实模型请求 0 次 |
73
+ | 发布流程 | YAML 解析及验证依赖检查通过;发布复用完整 CI 产生的同一份包,tag 与版本校验已加入;本轮未执行云端发布 |
74
+
75
+ 主题测试原有清理钩子 10 秒预算在本机不足:诊断时 `browser.close()` 约 14.5 秒。现为明确的 30 秒预算,浏览器关闭异常时仍清理服务器,完整测试正常退出。
76
+
77
+ 保护匹配改为候选扫描。连续中文 4k/8k/16k/32k,在 5 次预热、50 次重复的本机测试中均值约为 0.189/0.345/0.711/1.405ms;此前 8k 单次探针约 5.84s。测量方法与重复次数不同,不据此给出精确加速倍数,也不把合成输入当作真实用户平均延迟。最大长度回归另设宽松时间上限,以捕获秒级同步阻塞。
78
+
79
+ 本地输出在 `.test-runtime/verification-tests.txt`、`.test-runtime/verification-web.txt`、`.test-runtime/protection-benchmark.json` 与 `.test-runtime/web/result.json`。这些临时运行记录不随仓库发布;README 截图使用本轮实际生产组件夹具渲染。
80
+
81
+ 本轮没有修改用户的实时 DSH 实例或使用真实模型。60 条模型质量集仍为 `not_evaluated`;原生中文 IME 候选组合、完整宿主及其他插件组合仍不能仅由本地夹具宣称验证通过。
82
+
83
+ ## 2026-10 历史记录
84
+
85
+ 记录日期:2026 年 10 月 22 日(Asia/Shanghai)。下表记录开发机上的实际执行证据;其中的 `.test-runtime/` 是本仓库的临时证据目录(已被 `.gitignore` 排除),公开仓库不包含这些文件,列出的路径用于说明证据来源与生成方式,读者可在本地运行对应命令复现。
86
+
87
+ `0.1.2` 的修正与新增证据见文末「0.1.2 修正复验」一节;`0.1.1` 时期的历史记录按原样保留,其中的测试计数(105)和版本号不再代表当前产物。
88
+
89
+ ## 当前状态
90
+
91
+ | 检查 | 状态 | 证据或待办 |
92
+ |---|---|---|
93
+ | DSH 目标版本发布契约 | 已核对 | `0.2.1-rc.2` 官方 conversation、LLM 等发布包 |
94
+ | 60 条固定合成评测集 | 结构已校验,尚未经独立人工标注 | 由开发助手编写;optimize/next/complete 各 20 条,next、complete 各 8 条弃权案例 |
95
+ | 离线评分空结果处理 | 已执行 | `evaluation/status.json`:0/60,`not_evaluated`,0 次模型调用 |
96
+ | 评测脚本黑盒测试 | 8/8 通过 | `node node_modules/vitest/vitest.mjs run tests/evaluation.test.ts` |
97
+ | 实际提示词导出与后处理合同 | 已执行 | 60 条调用真实 `lib/core.js` 导出;保护与弃权往返、raw 评分导入通过,0 次模型调用 |
98
+ | 自动化测试 | 105/105 通过(`0.1.1` 时期);TypeScript 通过 | 12 个测试文件;含真实 Edge 主题/灰字、设置竞态、取消、存储、评测工具及实际安装包 Loader;命令输出 `pnpm test` 的输出 |
99
+ | 实际 `.tgz` 的官方 Loader 加载 | 已通过 | `scripts/verify-package.mjs` 验证实际打包产物;启用、禁用、再启用、卸载及保留显式暂存草稿均已覆盖 |
100
+ | 内置 CLI 隔离安装与移除 | 已通过 | `dsh plugin --profile <name> add <tgz>` 的隔离安装记录:隔离 `DSH_HOME` 中安装、配置层解析、remove 后依赖/层/链接清理;0 次模型请求,未改桌面 profile |
101
+ | Edge 中真实编辑器输入回归 | 已通过 | `pnpm test:web` 的输出:Microsoft Edge headless、真实 Lexical 与生产 React 控制器;0 次付费模型调用 |
102
+ | 完整官方 Web 应用组合回归 | 未单独标记通过 | 浏览器编辑器夹具通过不等于所有官方 Web 组合与其他插件组合已验证 |
103
+ | 官方桌面端安装与升级 | 已通过 | 最终版本 `0.1.1`,内置 CLI 安装;宿主/浏览器文件哈希与构建一致。首次热加载可用;本次升级完全退出并重启 DSH 后才载入新宿主实例 |
104
+ | 桌面真实宿主 Gateway 接口 | 已通过 | 最终 `node tests/support/run-desktop-probe.mjs` 生成的报告:加载 `0.1.1`、认证 Gateway 状态/草稿 CRUD/清理;0 次生成请求 |
105
+ | 官方桌面端原生输入回归 | 已列场景通过,未宣称全覆盖 | `node tests/support/run-desktop-probe.mjs` 的人工观察记录:中文/emoji、优化、diff、还原、暂存、追加、Tab 采纳及相关一次撤销通过;IME 与附件/引用等组合仍未全部手测 |
106
+ | DSH 设置专属页与模块开关 | 原生访问和保存通过 | 账号菜单 → 设置 → 输入助手;四开关、三档强度及高级设置可见,实际保存优化开关/深度强度后恢复标准配置;高级参数边界与失败由自动化覆盖 |
107
+ | 深色主题、裁剪与设置竞态修复 | 已通过 | 原生菜单颜色与顶部显示复验;真实 Edge 测试覆盖灰字/候选定位,受控回归覆盖失败不重试、旧状态不覆盖设置、关闭期间暂存不清空 |
108
+ | 原生灰字与 Tab | 已通过,0 付费请求 | 临时本地 adapter 精确返回固定后缀;正式插件与官方编辑器显示灰字、Tab 采纳且不发送、Ctrl+Z 一次撤销。`node tests/support/run-desktop-completion-fixture.mjs` 生成的完成标记 确认路由与设置已清理 |
109
+ | 原生测试暂存精确清理 | 已通过 | `node tests/support/run-desktop-model-probe.mjs` 的清理记录:删除 1 条精确匹配测试稿,剩余 0 条,未碰其他暂存 |
110
+ | 真实模型小样本对照 | 6 次已完成,非完整质量验收 | 输入 2,706 + 输出 101 = 2,807 tokens;每种操作仅 1 个案例、各候选/基线一次。另一次桌面优化用量未知;见 `docs/smoke-comparison.md` |
111
+ | 60 条完整真实模型质量评测 | 未执行 | `evaluation/status.json` 仍为 0/60、`not_evaluated`;不能报告整套准确率或优于竞品 |
112
+
113
+ 发行包的自动预测与续写默认均开启;本次在当前机器安装时已将两个开关关闭,以避免测试期间顺带发生模型调用。设置可以由用户在插件菜单中显式开启。
114
+
115
+ 观察记录中的 `themeFixReverified` 和 `cleanupCompleted` 均已为 true。临时 adapter、探针、测试暂存与自有 quiet 配置块已清理;输入框恢复原先空稿,自动两开关的持久设置保持关闭,人工优化与暂存开启、强度为标准。没有开启或更改 DSH 的开发者工具偏好。
116
+
117
+ 本机包管理器曾复用同版本同路径的旧 `.tgz`,`--force` 也未更新实际文件。最终使用新的 `0.1.1` 文件名安装,并比对 `lib/index.js`、`lib/client.js` 哈希。升级后仍需完全退出并重新打开 DSH,不能把文件已更新等同于旧宿主实例已切换。
118
+
119
+ 实现者在完成实际执行后更新本表并注明命令、日期和结果;失败与未执行应保留。
120
+
121
+ ## 已执行的浏览器与桌面证据
122
+
123
+ Edge 夹具使用生产输入助手界面和控制器、真实 Lexical 编辑器,确认:优化回填后原生一次撤销恢复原文;改动查看和显式还原正常;暂存先保存再清空、仅经用户操作恢复;测量灰字后 Tab 插入正确。它使用测试模型输出,没有付费模型调用,记录中 `realDshDesktop:false`。
124
+
125
+ 桌面探针运行在真正的 DeepSeek Harness 可执行进程中,核对加载服务确属已安装的 `dsh-input-assistant@0.1.0`。通过认证 Gateway 调用 `settings/get`、`status`、`drafts/list`、`drafts/save`、`drafts/delete` 和 `drafts/clear`,完成草稿持久化往返、单条删除、按会话隔离及清空。报告 `generatedRequests:0`,没有写入会话事件;探针结束后清除了测试草稿并拆除探针连接。该证据验证了真实宿主接线,尚不能替代生产编辑器的完整原生交互验收。
126
+
127
+ 原生桌面操作使用可见的官方生产界面,没有向编辑器注入脚本:输入一条含中文和 emoji 的合成草稿,暂存后清空,一次 Ctrl+Z 精确恢复;显式追加暂存文字后,一次 Ctrl+Z 撤回追加;通过真实按钮调用辅助模型并回填,打开 diff,再还原原文。一次 Ctrl+Z 撤销还原,下一次 Ctrl+Z 撤销优化。验证完成后恢复起初的空草稿,并通过精确内容匹配清除测试暂存,保留用户其他数据。这些覆盖了已列出的操作;中文字符输入不等于已验证中文 IME 候选组合。
128
+
129
+ 小样本使用 `deepseek-account / deepseek-flash`,6 次均记录为最低推理档 `off`、temperature 0、256 输出 token 上限。公开基线只是提示词研究适配,没有运行其完整插件。fishcg 的提取适配有一处语气提示偏差,报告保留了该限制;样例接近部分参考提示词示例,另有明显样本偏差。不能把这些结果解释为同类领先,完整 60 条结果与人工语义评分继续保持 `not_evaluated`。[完整小样本说明](smoke-comparison.md)
130
+
131
+ ## 工程验收清单
132
+
133
+ - [x] 对实际分发 `.tgz` 使用官方 Loader 检查配置层及入口;同包安装到官方桌面 profile 并热加载。
134
+ - [x] Loader 生命周期及 CLI 隔离安装、配置解析和移除通过;桌面热加载和宿主接口另有实际记录。
135
+ - [ ] 整稿、选区、Tab 采纳、还原、暂存清空、追加及替换均只产生一次可撤销编辑。
136
+ - [ ] 中英文、emoji、多行文本的选区与范围准确。
137
+ - [ ] 输入、发送、新回合、切模型、切会话、断线、卸载后的迟到结果不会改写新稿。
138
+ - [ ] 中文输入法、`/` 与 `@` 原生菜单、Tab 焦点移动和已消费键事件互不抢占。
139
+ - [ ] 缩放、滚动、换行、输入框重挂后灰字定位正确;无法定位时隐藏。
140
+ - [ ] 普通附件原样保留;引用标签不被静默移除;不支持的范围有解释。
141
+ - [ ] 草稿保存失败不清空,三条上限、删除、重启恢复及会话隔离有效。
142
+ - [ ] 缺模型、超时、空输出、损坏保护映射及取消均保留原稿。
143
+ - [ ] 官方桌面端使用同一 `.tgz` 单独验证,不能用 Web 通过替代。
144
+
145
+ ## 质量验收清单
146
+
147
+ - [ ] 保留准确的模型、提供商、推理档、预算和候选/基线版本。
148
+ - [ ] 60 条案例均有实际生成结果,失败项明确记录或重跑。
149
+ - [ ] 44 条预期文字结果均完成人工语义评审。
150
+ - [ ] 对照报告意图符合、无根据新增要求、弃权与延迟,而非只报告采纳率。
151
+ - [ ] 原文保护完整;重大约束丢失和新增实质任务或授权为零。
152
+
153
+ 完整流程见 [质量评测说明](evaluation.md)。
154
+
155
+ ## 0.1.2 修正复验
156
+
157
+ 记录日期:2026 年 10 月 23 日(Asia/Shanghai)。逐条复现与修复说明见 [0.1.2 修正记录](CHANGELOG-0.1.2.md)。
158
+
159
+ | 检查 | 状态 | 证据 |
160
+ |---|---|---|
161
+ | TypeScript | 通过 | `node node_modules/typescript/bin/tsc --noEmit`,无输出 |
162
+ | 自动化测试 | **121/121 通过** | 12 个测试文件;`node node_modules/vitest/vitest.mjs run` |
163
+ | 实际 `.tgz` 的官方 Loader 加载 | 通过 | `node scripts/verify-package.mjs dist/dsh-input-assistant-0.1.2.tgz` |
164
+ | 真实 Edge 编辑器回归 | 通过 | `node scripts/smoke-web.mjs`:4 项断言,0 次付费模型调用 |
165
+ | 评测集结构 | 通过 | `node scripts/evaluate.mjs validate`:60 例,16 条弃权 |
166
+ | 构建可复现 | 通过 | 重新 `scripts/build.mjs` 后 `lib/` 与打包产物逐字节一致 |
167
+ | 归档校验 | 通过 | `verify-archive.mjs`:32,5xx 个普通文件全部通过大小与 SHA256 |
168
+ | 恢复脚本幂等 | 通过 | 第二次运行 `restore-windows.mjs` 报告 `restoredDirectories: 0`、`unchangedLinks: 2755`、`completed: true` |
169
+ | 恢复后可构建可测试 | 通过 | 从外层 ZIP 干净解压 → 随包 Node → `restore-windows` → `tsc` → 121 条测试全部通过 |
170
+
171
+ 本次修正**没有**新增真实模型调用。以下状态与 `0.1.1` 一致,不因本次修正而改变:
172
+
173
+ - 60 条固定合成质量集仍为 `not_evaluated`(0/60),未做人工语义标注。
174
+ - 6 次小样本对照的结论不变,仍不能据此排名或宣称领先。
175
+ - 中文 IME 候选组合、附件/引用组合、完整官方 Web 组合、其他插件组合、非 Windows x64 平台仍未验证。
176
+ - 本次未在官方桌面端重新做原生手测;桌面端证据仍来自 `0.1.1` 时期,不能写成 `0.1.2` 已在新设备验收。
177
+
178
+ ### 关于恢复脚本的更正
179
+
180
+ 开发过程中曾把"恢复脚本在 `originallyMissing` 链接处失败"记为 `0.1.1` 的阻断性缺陷。复核确认该现象由**开发会话沙箱对工作区盘符的文件系统重定向**引起(junction 被写成 `\??\Global\…`,同一进程无法跟随),不属于归档或脚本缺陷:在普通用户路径(C 盘临时目录、随包 Node 24.19.0)上,`0.1.1` 原始归档的完整流程可正常完成,105 条测试全部通过。`0.1.2` 对恢复脚本的改动因此是**健壮性改进**(幂等、`--repair`、缺目标跳过、链接识别、创建兜底),不是对既有缺陷的修复。
@@ -0,0 +1,11 @@
1
+ import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
2
+ import type { BrowserRuntime } from './runtime.js';
3
+ type RuntimeProps = {
4
+ runtime: BrowserRuntime;
5
+ };
6
+ type RightProps = PropsRuntime<'conversation.input.right'> & RuntimeProps;
7
+ type OverlayProps = PropsRuntime<'conversation.input.overlay'> & RuntimeProps;
8
+ /** The right slot owns input observation; the overlay only paints the same controller's state. */
9
+ export declare function AssistantRight({ runtime, sessionId, useInput, useSession, inputActions }: RightProps): import("react").JSX.Element;
10
+ export declare function AssistantOverlay({ runtime, sessionId }: OverlayProps): import("react").JSX.Element;
11
+ export {};
@@ -0,0 +1,187 @@
1
+ import { type AssistantConfig, type AssistantStatus, type GenerationRequest, type ModelRoute, type StoredDraft, type TokenSpan } from '../core/types.js';
2
+ import { type ReferenceOccurrence } from './dom.js';
3
+ export interface BrowserInput {
4
+ draft: string;
5
+ draftRev: number;
6
+ phase: string;
7
+ attachmentIds: readonly unknown[];
8
+ occurrences: readonly ReferenceOccurrence[];
9
+ }
10
+ export interface BrowserActions {
11
+ captureInsertion(): TokenSpan;
12
+ insertText(text: string, span: TokenSpan): boolean;
13
+ persistDraft?(): void;
14
+ }
15
+ export interface BrowserBinding {
16
+ sessionId: string;
17
+ input: BrowserInput;
18
+ actions: BrowserActions;
19
+ editor: HTMLElement | null;
20
+ running: boolean;
21
+ route?: ModelRoute;
22
+ }
23
+ export interface BrowserTransport {
24
+ call<T>(method: string, data: unknown, signal?: AbortSignal): Promise<T>;
25
+ generation(): string | null;
26
+ }
27
+ export interface Suggestion {
28
+ text: string;
29
+ snapshot: GenerationRequest;
30
+ kind: 'next' | 'complete';
31
+ }
32
+ export interface OptimizationPreview {
33
+ request: GenerationRequest;
34
+ text: string;
35
+ beforeTarget: string;
36
+ clipboardStart: number;
37
+ clipboardEnd: number;
38
+ clientGeneration: string | null;
39
+ }
40
+ export interface UndoSnapshot {
41
+ recent: readonly StoredDraft[];
42
+ expiresAt: number;
43
+ pending: readonly StoredDraft[];
44
+ generation: string | null;
45
+ }
46
+ export type SuggestionStatus = 'idle' | 'waiting' | 'generating' | 'ready' | 'throttled' | 'abstained' | 'failed' | 'paused';
47
+ export interface ChangeRecord {
48
+ before: string;
49
+ after: string;
50
+ beforeTarget: string;
51
+ afterTarget: string;
52
+ span: TokenSpan;
53
+ sourceTurnId: string | null;
54
+ connectionGeneration: string;
55
+ routeKey: string;
56
+ clientGeneration: string | null;
57
+ }
58
+ export interface BrowserState {
59
+ status: AssistantStatus | null;
60
+ settings: AssistantConfig;
61
+ busy: 'optimize' | 'stash' | null;
62
+ stashClearCancelled: boolean;
63
+ stashClearPending: boolean;
64
+ notice: string;
65
+ suggestion: Suggestion | null;
66
+ suggestionStatus: SuggestionStatus;
67
+ suggestionMessage: string;
68
+ preview: OptimizationPreview | null;
69
+ change: ChangeRecord | null;
70
+ drafts: readonly StoredDraft[];
71
+ deletedDrafts: readonly StoredDraft[];
72
+ pendingUndoDrafts: readonly StoredDraft[];
73
+ locked: readonly string[];
74
+ connected: boolean;
75
+ settingsSaving: boolean;
76
+ metrics: UsageMetrics;
77
+ }
78
+ export interface UsageMetrics {
79
+ exposures: number;
80
+ accepted: number;
81
+ editedAcceptances: number;
82
+ editedCharacters: number;
83
+ calls: number;
84
+ totalLatencyMs: number;
85
+ }
86
+ /** One controller per mounted composer. Right/overlay surfaces consume this same store. */
87
+ export declare class InputAssistantController {
88
+ readonly sessionId: string;
89
+ private readonly transport;
90
+ private readonly saveSettings?;
91
+ private state;
92
+ private listeners;
93
+ private binding;
94
+ private active;
95
+ private timer;
96
+ /** Cache key the armed completion timer was scheduled for; null when no timer is armed. */
97
+ private timerKey;
98
+ private manualTimerKey;
99
+ private poll;
100
+ private undoTimer;
101
+ private undoExpiresAt;
102
+ private readonly requestPrefix;
103
+ private completionRetryAt;
104
+ private polling;
105
+ private lifecycle;
106
+ private disposed;
107
+ private composing;
108
+ private settingsPending;
109
+ private settingsEpoch;
110
+ private draftsEpoch;
111
+ private stashEpoch;
112
+ private nextTurns;
113
+ private failedNextKey;
114
+ private nextCache;
115
+ private completionCache;
116
+ private failedCompletionKey;
117
+ private lastCompletionStart;
118
+ private suppressUntilEdit;
119
+ private sequence;
120
+ private clientGeneration;
121
+ private lockedRanges;
122
+ private exposed;
123
+ private acceptance;
124
+ constructor(sessionId: string, transport: BrowserTransport, metrics?: UsageMetrics, saveSettings?: ((update: Partial<AssistantConfig>) => Promise<AssistantConfig>) | undefined, undo?: UndoSnapshot);
125
+ getUndoSnapshot(): UndoSnapshot;
126
+ private armUndoExpiry;
127
+ getSnapshot: () => BrowserState;
128
+ subscribe: (listener: () => void) => (() => void);
129
+ private patch;
130
+ start(): void;
131
+ private visibilityChanged;
132
+ private schedulePoll;
133
+ dispose(): void;
134
+ bind(binding: BrowserBinding): void;
135
+ notifySelectionChange(): void;
136
+ setComposing(value: boolean): void;
137
+ dismissSuggestion(): void;
138
+ dismissOptimization(): void;
139
+ cancelOperation(): void;
140
+ clearNotice(): void;
141
+ notice(text: string): void;
142
+ refresh(): Promise<void>;
143
+ updateSettings(update: Partial<AssistantConfig>): Promise<void>;
144
+ beginSettingsUpdate(): void;
145
+ endSettingsUpdate(): void;
146
+ /** A settings page can update every mounted composer without waiting for its status poll. */
147
+ applySettings(settings: AssistantConfig): void;
148
+ lockSelection(): void;
149
+ clearLocks(): void;
150
+ optimize(): Promise<void>;
151
+ applyOptimization(): boolean;
152
+ canRestore(): boolean;
153
+ restoreOriginal(): boolean;
154
+ acceptSuggestion(): boolean;
155
+ /** Called only after the overlay has actually rendered a candidate. */
156
+ markExposed(requestId: string): void;
157
+ refreshDrafts(): Promise<void>;
158
+ stash(replaceId?: string): Promise<void>;
159
+ restoreDraft(draft: StoredDraft, mode: 'append' | 'replace'): boolean;
160
+ deleteDraft(id: string): Promise<void>;
161
+ clearDrafts(): Promise<void>;
162
+ private mutateDraft;
163
+ undoDeleteDrafts(target?: 'recent' | 'pending'): Promise<void>;
164
+ discardPendingUndo(): void;
165
+ retrySuggestion(): void;
166
+ private eligibleForManual;
167
+ private suggestionStatus;
168
+ private captureTarget;
169
+ private pureText;
170
+ private eligible;
171
+ private driveSuggestions;
172
+ private requestSuggestion;
173
+ private snapshot;
174
+ private begin;
175
+ private observeAcceptedEdit;
176
+ private isCurrent;
177
+ private validResult;
178
+ private sameCaret;
179
+ private routeKey;
180
+ private nextKey;
181
+ private completionKey;
182
+ private invalidate;
183
+ private clearTimer;
184
+ private cancelActive;
185
+ private recordLatency;
186
+ private errorMessage;
187
+ }
@@ -0,0 +1,29 @@
1
+ import type { TokenSpan } from '../core/types.js';
2
+ export interface ReferenceOccurrence {
3
+ offset: number;
4
+ length: number;
5
+ }
6
+ export declare const CHIP_SELECTOR = "[data-composer-chip],[data-composer-text-ref],[data-composer-command]";
7
+ export declare function findEditor(anchor: HTMLElement | null): HTMLElement | null;
8
+ export declare function focusedIn(editor: HTMLElement | null): boolean;
9
+ export declare function referenceOverlaps(span: TokenSpan, references: readonly ReferenceOccurrence[]): boolean;
10
+ /** Public InputState references use clipboard offsets; TokenSpan uses one character per reference. */
11
+ export declare function clipboardOffset(detectOffset: number, references: readonly ReferenceOccurrence[]): number;
12
+ export declare function selectedPlainText(editor: HTMLElement | null, draft: string, span: TokenSpan, references: readonly ReferenceOccurrence[]): {
13
+ text: string;
14
+ clipboardStart: number;
15
+ clipboardEnd: number;
16
+ } | null;
17
+ export interface GhostGeometry {
18
+ left: number;
19
+ top: number;
20
+ width: number;
21
+ maxHeight: number;
22
+ font: string;
23
+ lineHeight: string;
24
+ letterSpacing: string;
25
+ }
26
+ /** Read-only DOM measurements; failure hides the decoration instead of guessing padding. */
27
+ export declare function measureGhost(editor: HTMLElement | null, empty: boolean): GhostGeometry | null;
28
+ export declare function nativeMenuOpen(editor: HTMLElement | null): boolean;
29
+ export declare function canUseTab(event: KeyboardEvent, editor: HTMLElement | null, composing: boolean): boolean;
@@ -0,0 +1,21 @@
1
+ export interface ViewportBounds {
2
+ left: number;
3
+ top: number;
4
+ width: number;
5
+ height: number;
6
+ }
7
+ export interface AnchorBounds {
8
+ left: number;
9
+ top: number;
10
+ right: number;
11
+ bottom: number;
12
+ width: number;
13
+ }
14
+ export interface FloatingPlacement {
15
+ left: number;
16
+ top: number;
17
+ width: number;
18
+ maxHeight: number;
19
+ }
20
+ /** Keep the entire scrollable surface in the visible viewport, independent of composer clipping. */
21
+ export declare function placeFloating(anchor: AnchorBounds, contentHeight: number, viewport: ViewportBounds, preferredWidth?: number): FloatingPlacement;
@@ -0,0 +1,6 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ export declare const name = "input-assistant.client";
3
+ export declare const inject: string[];
4
+ /** Slot registration stays inside the mounted fiber; unloading owns all timers and DOM. */
5
+ export declare function apply(ctx: Context): void;
6
+ export { BrowserRuntime, InputAssistantController } from './public.js';
@@ -0,0 +1,2 @@
1
+ export { BrowserRuntime } from './runtime.js';
2
+ export { InputAssistantController } from './controller.js';
@@ -0,0 +1,55 @@
1
+ import { InputAssistantController, type BrowserTransport } from './controller.js';
2
+ import type { AssistantConfig } from '../core/types.js';
3
+ export interface ConnectionFace {
4
+ rpc: {
5
+ call(channel: string, endpoint: string, payload: unknown, signal?: AbortSignal): Promise<{
6
+ ok: true;
7
+ value: unknown;
8
+ } | {
9
+ ok: false;
10
+ error: {
11
+ code?: string;
12
+ message?: string;
13
+ };
14
+ }>;
15
+ };
16
+ generation: {
17
+ getSnapshot(): {
18
+ id: number;
19
+ } | undefined;
20
+ subscribe(listener: () => void): () => void;
21
+ };
22
+ }
23
+ export interface ModelDirectoryFace {
24
+ directoryFor(sessionId: string): {
25
+ store: {
26
+ getSnapshot(): {
27
+ current: {
28
+ provider: string;
29
+ model: string;
30
+ } | null;
31
+ };
32
+ subscribe(listener: () => void): () => void;
33
+ };
34
+ load(): Promise<unknown>;
35
+ };
36
+ }
37
+ export declare class BrowserRuntime {
38
+ readonly connection: ConnectionFace;
39
+ readonly models?: ModelDirectoryFace | undefined;
40
+ private entries;
41
+ private disposed;
42
+ private lifetime;
43
+ private pendingSettings;
44
+ private settingsQueue;
45
+ private metrics;
46
+ private undo;
47
+ readonly transport: BrowserTransport;
48
+ constructor(connection: ConnectionFace, models?: ModelDirectoryFace | undefined);
49
+ controllerFor(sessionId: string): InputAssistantController;
50
+ retain(sessionId: string): () => void;
51
+ private saveUndo;
52
+ applySettings(settings: AssistantConfig): void;
53
+ saveSettings(update: Partial<AssistantConfig>): Promise<AssistantConfig>;
54
+ dispose(): void;
55
+ }
@@ -0,0 +1,8 @@
1
+ import type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
2
+ import type { BrowserRuntime } from './runtime.js';
3
+ type SettingsProps = PropsRuntime<'settings.section'> & {
4
+ runtime: BrowserRuntime;
5
+ };
6
+ /** A root-scoped DSH settings section; works even when no composer is mounted. */
7
+ export declare function AssistantSettings({ runtime }: SettingsProps): import("react").JSX.Element;
8
+ export {};
@@ -0,0 +1 @@
1
+ export declare const STYLE_TEXT = "\n.dsh-ia {\n --dsh-ia-fallback-bg: #ffffff;\n --dsh-ia-fallback-fg: #111827;\n --dsh-ia-fallback-muted: #4b5563;\n --dsh-ia-fallback-border: #d1d5db;\n --dsh-ia-accent: var(--dsw-alias-state-business-primary, #3b82f6);\n --dsh-ia-accent-subtle: rgba(59, 130, 246, 0.1);\n --dsh-ia-pill-bg: var(--dsw-alias-interactive-bg-subtle, rgba(0, 0, 0, 0.04));\n --dsh-ia-pill-hover: var(--dsw-alias-interactive-bg-hover, rgba(0, 0, 0, 0.08));\n font-family: var(--dsw-font-family, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif);\n color: var(--dsw-alias-label-primary, var(--dsh-ia-fallback-fg));\n font-size: 13px;\n line-height: 1.5;\n box-sizing: border-box;\n color-scheme: light;\n}\n\nbody[data-ds-dark-theme] .dsh-ia {\n --dsh-ia-fallback-bg: #1f2329;\n --dsh-ia-fallback-fg: #f3f4f6;\n --dsh-ia-fallback-muted: #9ca3af;\n --dsh-ia-fallback-border: #374151;\n --dsh-ia-pill-bg: var(--dsw-alias-interactive-bg-subtle, rgba(255, 255, 255, 0.06));\n --dsh-ia-pill-hover: var(--dsw-alias-interactive-bg-hover, rgba(255, 255, 255, 0.12));\n color-scheme: dark;\n}\n\n.dsh-ia * { box-sizing: border-box; }\n.dsh-ia button, .dsh-ia input, .dsh-ia select { font: inherit; color: inherit; }\n\n/* Global buttons within dsh-ia */\n.dsh-ia button {\n border: 1px solid var(--dsw-alias-border-l2, var(--dsh-ia-fallback-border));\n border-radius: 7px;\n padding: 5px 11px;\n background: var(--dsw-alias-bg-layer-1, transparent);\n color: var(--dsw-alias-label-primary, inherit);\n cursor: pointer;\n transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease, opacity 0.15s ease, transform 0.15s ease;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 5px;\n}\n.dsh-ia button:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover, #8882);\n border-color: var(--dsw-alias-state-business-primary, var(--dsh-ia-accent));\n}\n.dsh-ia button:active:not(:disabled) {\n transform: translateY(1px);\n}\n.dsh-ia button:disabled {\n opacity: 0.45;\n cursor: default;\n transform: none;\n}\n.dsh-ia button:focus-visible, .dsh-ia input:focus-visible, .dsh-ia select:focus-visible {\n outline: 2px solid var(--dsw-alias-state-business-primary, #3b82f6);\n outline-offset: 2px;\n}\n\n/* Smart Pill Trigger Group in Input Card */\n.dsh-ia-root {\n display: inline-flex;\n align-items: center;\n background: var(--dsh-ia-pill-bg);\n border: 1px solid var(--dsw-alias-border-l2, var(--dsh-ia-fallback-border));\n border-radius: 8px;\n padding: 2px;\n gap: 2px;\n position: relative;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);\n}\n.dsh-ia-root .dsh-ia-trigger {\n border: none;\n background: transparent;\n padding: 4px 10px;\n font-weight: 500;\n border-radius: 6px;\n white-space: nowrap;\n}\n.dsh-ia-root .dsh-ia-trigger:hover:not(:disabled) {\n background: var(--dsh-ia-pill-hover);\n}\n.dsh-ia-root .dsh-ia-menu-btn {\n border: none;\n background: transparent;\n padding: 4px 6px;\n border-radius: 6px;\n min-width: 24px;\n}\n.dsh-ia-root .dsh-ia-menu-btn:hover:not(:disabled) {\n background: var(--dsh-ia-pill-hover);\n}\n.dsh-ia-root .dsh-ia-cancel-btn {\n border: none;\n background: rgba(239, 68, 68, 0.12);\n color: #ef4444;\n font-size: 11px;\n padding: 4px 8px;\n border-radius: 6px;\n}\n.dsh-ia-root .dsh-ia-cancel-btn:hover {\n background: rgba(239, 68, 68, 0.2);\n}\n\n/* Floating Menu Panel */\n.dsh-ia-menu {\n position: fixed;\n width: min(480px, calc(100vw - 24px));\n max-height: calc(100dvh - 24px);\n overflow-y: auto;\n overscroll-behavior: contain;\n padding: 16px;\n border: 1px solid var(--dsw-alias-border-l2, var(--dsh-ia-fallback-border));\n border-radius: 14px;\n background: var(--dsw-alias-bg-layer-2, var(--dsh-ia-fallback-bg));\n box-shadow: 0 12px 36px rgba(0, 0, 0, 0.22);\n z-index: 1000;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.dsh-ia-preview {\n z-index: 1001;\n width: min(580px, calc(100vw - 24px));\n}\n.dsh-ia-preview .dsh-ia-pre {\n margin-top: 10px;\n max-height: 360px;\n}\n\n/* Form Controls & Fields */\n.dsh-ia-row {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n margin: 6px 0;\n}\n.dsh-ia-row label {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n cursor: pointer;\n user-select: none;\n}\n.dsh-ia-field {\n display: flex;\n flex-direction: column;\n gap: 5px;\n margin: 6px 0;\n}\n.dsh-ia-field input, .dsh-ia select {\n border: 1px solid var(--dsw-alias-border-l2, var(--dsh-ia-fallback-border));\n border-radius: 7px;\n background: var(--dsw-alias-bg-layer-1, var(--dsh-ia-fallback-bg));\n padding: 7px 10px;\n color: var(--dsw-alias-label-primary, inherit);\n transition: border-color 0.15s ease;\n}\n.dsh-ia-field input:focus, .dsh-ia select:focus {\n border-color: var(--dsw-alias-state-business-primary, var(--dsh-ia-accent));\n}\n.dsh-ia-field input { width: 100%; }\n.dsh-ia-muted {\n color: var(--dsw-alias-label-secondary, var(--dsh-ia-fallback-muted));\n font-size: 12px;\n line-height: 1.45;\n}\n\n/* Sections */\n.dsh-ia-section {\n border-top: 1px solid var(--dsw-alias-border-l2, var(--dsh-ia-fallback-border));\n margin-top: 8px;\n padding-top: 10px;\n}\n.dsh-ia-section h4 {\n font-size: 13px;\n margin: 0 0 8px;\n font-weight: 600;\n}\n\n/* Notices & Alerts */\n.dsh-ia-notice {\n position: fixed;\n max-width: min(360px, calc(100vw - 32px));\n overflow: auto;\n padding: 6px 12px;\n background: var(--dsw-alias-bg-layer-2, var(--dsh-ia-fallback-bg));\n border: 1px solid var(--dsw-alias-border-l2, var(--dsh-ia-fallback-border));\n border-radius: 20px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.14);\n z-index: 1002;\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n animation: dshIaFadeIn 0.2s ease-out;\n}\n@keyframes dshIaFadeIn {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: translateY(0); }\n}\n.dsh-ia-menu .dsh-ia-notice {\n position: static;\n max-width: 100%;\n margin: 6px 0;\n box-shadow: none;\n}\n.dsh-ia-notice button { margin-left: 6px; padding: 3px 8px; font-size: 11px; }\n\n/* Diff / Pre formatting */\n.dsh-ia-pre {\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n font: inherit;\n font-size: 12px;\n max-height: 200px;\n overflow-y: auto;\n padding: 10px;\n border: 1px solid var(--dsw-alias-border-l2, var(--dsh-ia-fallback-border));\n border-radius: 8px;\n background: var(--dsw-alias-bg-module-platform, rgba(128, 128, 128, 0.08));\n}\n.dsh-ia-diff ins {\n background: rgba(39, 163, 91, 0.22);\n color: #107c41;\n text-decoration: none;\n border-radius: 2px;\n padding: 0 2px;\n}\nbody[data-ds-dark-theme] .dsh-ia-diff ins {\n color: #4ade80;\n background: rgba(34, 197, 94, 0.22);\n}\n.dsh-ia-diff del {\n background: rgba(217, 69, 69, 0.22);\n color: #c42b1c;\n text-decoration: line-through;\n border-radius: 2px;\n padding: 0 2px;\n}\nbody[data-ds-dark-theme] .dsh-ia-diff del {\n color: #f87171;\n background: rgba(239, 68, 68, 0.22);\n}\n\n/* Draft Card */\n.dsh-ia-draft {\n border: 1px solid var(--dsw-alias-border-l2, var(--dsh-ia-fallback-border));\n border-radius: 9px;\n padding: 9px 12px;\n margin: 8px 0;\n background: var(--dsw-alias-bg-layer-1, transparent);\n transition: border-color 0.15s ease;\n}\n.dsh-ia-draft summary {\n cursor: pointer;\n overflow-wrap: anywhere;\n font-weight: 500;\n}\n.dsh-ia-draft time {\n display: block;\n font-size: 11px;\n color: var(--dsw-alias-label-tertiary, var(--dsh-ia-fallback-muted));\n margin: 3px 0 6px;\n}\n\n/* Candidate Panel & Ghost Text */\n.dsh-ia-candidate {\n position: fixed;\n display: flex;\n align-items: center;\n gap: 9px;\n padding: 10px 14px;\n max-width: min(640px, calc(100vw - 32px));\n max-height: 240px;\n overflow-y: auto;\n border: 1px solid var(--dsw-alias-border-l2, var(--dsh-ia-fallback-border));\n border-radius: 11px;\n background: var(--dsw-alias-bg-layer-2, var(--dsh-ia-fallback-bg));\n box-shadow: 0 6px 24px rgba(0, 0, 0, 0.2);\n pointer-events: auto;\n z-index: 998;\n}\n.dsh-ia-candidate-text {\n flex: 1;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n font-size: 13px;\n line-height: 1.5;\n}\n.dsh-ia-ghost {\n position: fixed;\n white-space: pre-wrap;\n word-break: break-word;\n overflow-wrap: break-word;\n overflow: hidden;\n max-height: 100%;\n pointer-events: none;\n user-select: none;\n color: var(--dsw-alias-label-tertiary, #76808d);\n opacity: 0.88;\n z-index: 34;\n}\n[data-composer-card]:has([data-dsh-ia-empty-ghost]) [data-composer-placeholder] {\n visibility: hidden;\n}\n\n/* Settings Form page */\n.dsh-ia-settings { width: 100%; max-width: 760px; }\n.dsh-ia-settings h2 { font-size: 18px; margin: 0 0 8px; }\n.dsh-ia-settings h3 { font-size: 14px; margin: 0 0 10px; font-weight: 600; }\n.dsh-ia-settings fieldset { padding: 0; margin: 0; border: 0; min-width: 0; }\n.dsh-ia-settings-toggles { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; }\n.dsh-ia-settings-toggles label { display: flex; align-items: center; gap: 7px; cursor: pointer; }\n.dsh-ia-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n}\n\n.dsh-ia-preview .dsh-ia-pre { max-height: 320px; }\n.dsh-ia-notice { flex-wrap: wrap; border-radius: 12px; }\n.dsh-ia-route, .dsh-ia-suggestion-state { overflow-wrap: anywhere; }\n.dsh-ia-suggestion-state { margin: 6px 0; }\n.dsh-ia-inline-status { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; color: var(--dsw-alias-label-secondary,var(--dsh-ia-fallback-muted)); }\n.dsh-ia summary:focus-visible { outline: 2px solid var(--dsh-ia-accent); outline-offset: 2px; }\n.dsh-ia-settings-presets { display: grid; grid-template-columns: repeat(auto-fit,minmax(180px,1fr)); gap: 10px; }\n.dsh-ia .dsh-ia-preset { display: flex; flex-direction: column; align-items: flex-start; text-align: left; padding: 12px; gap: 5px; }\n.dsh-ia .dsh-ia-preset[aria-pressed=true] { border-color: var(--dsh-ia-accent); background: var(--dsh-ia-accent-subtle); }\n.dsh-ia-setting-grid { display: grid; grid-template-columns: repeat(auto-fit,minmax(min(280px,100%),1fr)); gap: 14px; margin-top: 12px; }\n.dsh-ia-number-control { display: flex; align-items: center; gap: 10px; }\n.dsh-ia-number-control input[type=number] { width: 100px; flex: 0 0 auto; }\n.dsh-ia-number-control input[type=range] { min-width: 0; flex: 1; accent-color: var(--dsh-ia-accent); }\n.dsh-ia-setting-heading { display: flex; justify-content: space-between; gap: 8px; align-items: center; }\n.dsh-ia-setting-heading label { font-weight: 500; }\n@media (prefers-reduced-motion: reduce) { .dsh-ia *, .dsh-ia-notice { transition: none !important; animation: none !important; } }\n";