WeKnora
Tencent
Open-source LLM knowledge platform: turn raw documents into a queryable RAG, an autonomous reasoning agent, and a self-maintaining Wiki.
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:lhh010/dsh-paste-input
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
简体中文 | English
DSH WebUI 文件输入增强插件:Ctrl+V 粘贴 + 全页面拖拽 + 选择文件/文件夹,发送时复制进会话工作区临时附件目录,并把对话气泡里的附件文本块折叠为文件 chip。
派生自 dsh-external/dsh-multimedia-webui-input(MIT),在其基础上新增剪贴板粘贴输入、首次告知弹窗与气泡附件折叠。
你的 DSH 版本决定装哪个插件版本(装错会崩:常见症状
useConversation is not a function)
- DSH 0.1.2-alpha.1 ~ 0.2.1-alpha.1:装新版(下方默认命令;各 DSH 版本对应的插件 tag 见下方变更记录)
- 更旧的 DSH(0.1.1-rc.2 及以前):无可用版本
# 方式一:git 依赖固定 tag(公开镜像,推荐;也可用 github:lhh010/dsh-paste-input)
dsh plugin --profile web add '@dsh-community/dsh-paste-input@github:lhh010/dsh-paste-input#v0.2.7'
# 方式二:本地 link
# dsh plugin --profile web add link:/path/to/dsh-paste-input
并在 ~/.dsh/profiles/web/cordis.patch.yml 追加(热重载,无需重启):
- insert:
- id: dsh-paste-input
name: '@dsh-community/dsh-paste-input'
安装提示:pnpm 11 首次安装可能拦截 node-pty 等构建脚本——在
~/.dsh/profiles/web下执行pnpm approve-builds --all放行后重跑安装命令;装完硬刷新浏览器(Ctrl/Cmd+Shift+R)。
更新浮标会结合当前运行的 DSH 版本(宿主端从 dsh 安装清单读取)与仓库根的 compatibility.json(版本→支持的 DSH 列表,精确匹配)判定提示形态:
兼容数据拉取失败或无该版本条目时,自动回退为旧的普通升级提示(离线安全)。发版时需同步维护 compatibility.json(与版本表/变更记录同一步骤新增一行)。
修复(桌面端):双管齐下绕过桌面宿主两个缺陷(均只见于 dsh-app:// 桌面端,web 端不受影响;上游跟踪 discussion #8303):① 会话解析——ctx.sessions 在桌面端插件侧为空,改用 ctx.get('workspaceRegistry') 按 sessionIds→workspace.path 服务端解析 cwd(无客户端路径输入,不破坏原安全模型);② 上传传输——桌面转发层破坏二进制 PUT body(Content-Length 与实际字节不符),桌面端改走 base64 JSON 通道(POST /batches/<id>/files/<n>/base64),web 端保留二进制快路径。实机验证:桌面端粘贴→copied→发送成功,文件落盘 ✓。同时移除 v0.2.4/0.2.5 的“桌面端不可用”弹窗(已过时),保留 live-session-not-found toast 作为回归安全网。
声明:dsh 版本支持面与 v0.2.5 相同;双 bundle node --check 通过
修正:v0.2.4 弹窗与 toast 中的跟踪链接原指向内测反馈仓(外部不可见),改为公开的 deepseek-harness discussion #8303。其余与 v0.2.4 相同。
中间防御版:在桌面端弹窗提示“粘贴上传不可用”。该结论被 v0.2.6 的插件侧修复推翻(workspaceRegistry 会话解析 + base64 上传通道),误导性提示已随 tag 一并撤回(提交仍在历史中:0a9f131 / 06a02cb)。
声明:dsh 版本支持面与 v0.2.3 相同;双 bundle node --check 通过
node --check 通过node --check 通过node --check 通过node --check 通过/file 端点验证(要求真实发送目录的 owner marker 与文件清单声明),伪造/手打的 marker 块不再被折叠成官方样式的文件 chip,防止以假附件文本误导模型或阅读者add(sessionId, …) 的 sessionId 未定义(拖拽会以 toast 报错),改为 current.sessionIdnode --check 通过/dsh-paste-input/v1/latest 端点返回当前 DSH 版本;客户端更新判定结合 compatibility.json——最新版不支持当前 DSH 时显示琥珀色「需更高 DSH 版本」提示,支持中间版本时提示中间版node --check 通过适配 dsh 0.1.6-alpha.2 多实例重构:当前会话改由 uiSession.current({ key, ctx })解析(alpha.1 的 sessions.list.current 字段已移除,此前导致粘贴/拖拽/附件按钮全部弹「请先打开一个会话」);粘贴、拖拽、附件按钮三条路径均已切换,alpha.1 回退保留。lib node --check 全绿,alpha.2 实机验证 chips 恢复显示。
声明支持 dsh-v0.1.6-alpha.1(npm 已发布,钉版本实机验证;client 插件面零代码差异,lib node --check 全绿,实机加载正常)。安装命令统一更新为 #v0.2.7。
==== END DSH_PASTE_INPUT ==== 与旧缓存 bundle 写入的 ==== END DSH_PASTE_INPUT_V1 ====),解析器只认后者之外的现行格式导致旧消息折叠失败并刷 Console 警告;现兼容两种拼写。注:V1 结尾拼写为历史遗留(仅极早期 bundle 写入),后续版本可能不再兼容,依赖旧格式折叠的历史消息请尽快升级验证:alpha.2 改动为 Sidebar 文档预览、模型文件交付、minimal 默认工具调整与 fs-ext 安装修复,client 插件面零代码差异;npm 已发布,钉版本实机验证;同步 lib 内烙死的 PLUGIN_VERSION 常量(避免幻影自更新)
验证:0.1.5 改动在会话格式 V3 / ctx.agent 移除 / 宿主 client bundle 服务路由改 /plugins/?? 组合路由,client 插件面零代码差异;npm 已发布,钉版本实机验证,无需代码改动;启动清单确认加载
验证:alpha.2 改动全在 pi-ai / Web 顶栏 / 子代理消息 / host 面,client 插件面零代码差异;npm 已发布,钉版本实机验证,无需代码改动
sessionStorage——页面刷新后,输入框里残留的粘贴引用 chip 仍可正常发送(此前会报 "Attachment selection is no longer available in this browser tab")。+/-/0/Esc 快捷键、工具栏含缩放百分比/重置/复制完整路径/关闭;GIF 在查看器中持续播放GET /dsh-paste-input/v1/file?root=<发送目录>&path=<相对路径>:仅服务所有权标记(.dsh-paste-input.json)声明过的图片文件(SVG 除外,避免同域脚本执行),路径解析约束在发送目录内,单文件 ≤64 MiBbusy 变量,chip 一渲染即 ReferenceError,整个 dock 槽位被错误边界吞掉(表现:dock 上的附件气泡消失);已移除该悬空引用修复(AttachButton 崩溃):conversation.input.left 槽位不提供 owner props(无 input),props.input.phase 读取 undefined 崩溃(Console 报 Cannot read properties of undefined (reading 'phase'),槽位条目被框架错误边界捕获)。改用可选链 + 'plain' 默认值(add() 自身有 phase 守卫不会误操作)。dock 槽位的 occurrences 同样加防御
修复(403 刷屏):版本检查的 tag 源从 api.github.com(未认证限流 ~60 req/hr → 403)改为 data.jsdelivr.com/v1/packages/gh/(CDN,无限流,CORS 友好)
验证:alpha.5 为纯 bug 修复(升级路径问题),client 运行 API 无变更;lib 产物校验通过
修复(更新提示词):提示词新增第 0 步(先 dsh --version 确认本地 DSH 版本,对照 README「版本兼容」表选对应 tag,不匹配则改装)与第 3 步(安装失败/版本不匹配/启动报错先查 README「版本兼容」「已知限制」章节);原两步安装流程不变
修复(反复 403):GitHub tags API 在限流/未授权时返回 403,旧代码每次页面加载与点击重试都重新请求一次,console 被 403 刷屏。现按结果缓存到 localStorage:成功结果缓存 10 分钟、瞬时网络失败 60s、硬 403(限流)缓存 5 分钟——窗口内直接返回缓存结论不再发请求,手动「重试」仍可强制执行一次
降级文案:区分「网络不可达」与「GitHub 拒绝访问(限流/403)」——后者显示「版本检查暂不可用(GitHub 拒绝访问),已缓存」,不再误导为网络问题
修复:刚 push 新 tag 后的几分钟内,GitHub tags API / raw CDN 仍返回旧 tag,「已是最新版本」chip 会把旧的远端 tag 当作最新显示(如运行 0.1.10 却显示「已是最新 0.1.9」)。现取「拉到的 tag 与运行版本」中较新者展示;离线 chip 的重试路径同样处理
修复(删除失效 → unavailable):DSH 0.1.2-alpha 的输入机里 occurrence 的 offset/length 是 clipboard 投影坐标(chip 展开为完整 [attachment: …] 文本),而 consumeToken 的 span 校验在 detect 投影坐标(chip 仅占 1 个 U+FFFC 字符)下工作——旧代码直接把 clipboard 坐标传入导致替换必然失败,record 却已删除:dock chip 显示 unavailable、输入框 chip 残留。现按「前面每个 chip 缩短 length−1」精确换算成 detect 坐标再调用 consumeToken,失败时回退 setDraft 整段切除
修复(第二次粘贴报错 / 顶掉):insertReference 的插入点原来取 snapshot.draft.length(clipboard 投影长度),第一个附件存在后插入点越界 → The DSH composer changed before the attachment could be inserted。现同样按存活 chip 折算成 detect 坐标,多个附件可连续粘贴共存
新增(粘贴文件统一重命名):粘贴的文件统一改基础名——图片 paste_image.<ext>、其他文件 paste_file.<ext>(扩展名优先取原文件名,缺省按 MIME 补全);重名自动追加 (2)、(3)… 序号(以 composer 实时 chips + records 为冲突集),改名同步进上传路径。仅粘贴路径改名,拖拽与文件/文件夹选择保留原始文件名
验证:实机验证通过——连续粘贴两张截图得到 paste_image.png 与 paste_image(2).png 共存;dock × 删除上下同步;node --check 通过
验证:DSH npm 0.1.1-rc.1 实机 boot 验证通过——boot 清单包含本插件、client.js 返回 200;0.1.4 的 rc.8 适配(consumeToken 整段删除、appearance: 'file' 官方外观、内联 chip 整体编辑保护)在 0.1.1-rc.1 上行为无回归(所依赖的 inputTriggers.registerSource、conversation.input.for 门面与 conversation.input.left/dock、settings.section 槽位均保持不变)
@ + label 的完整行内区间(不再是 1 个占位符字符),v0.1.3 点击 dock chip 的 × 只删掉 @ 一个字符,输入框内残留附件文本。现改用 rc.8 官方删除动词 input.consumeToken(span CAS 整段切除),旧宿主回退为按 occurrence.length 切除📎 emoji 前缀与 8 字符截断(在 rc.8 上渲染为「蓝色 @ + 回形针 + 蓝色文件名」),label 改为纯文件名并附带官方 appearance: 'file',与官方 @file 引用的内联 chip 外观一致;完整路径与大小仍显示在输入框上方的 dock chip 中beforeinput,任何只触碰 chip 一部分的编辑(在 label 中间打字、退格删一个字符、选半截替换)都被阻止并把选区扩展到整个 chip(下一次按键即整体删除/替换);已完整选中整个 chip 的删除/替换放行。守卫通过 textarea.value === draft 识别 composer,不影响队列编辑等其他输入框;dock 的 × 按钮仍走 consumeToken 整段删除0.1.0-rc.8 实机验证——粘贴/拖拽 → dock chip → × 删除后输入框同步清空;发送 → 复制进附件目录 → 气泡折叠 chip 全链路可用slash → inputTriggers(lib/client.js 4 处:inject 数组 ×2 + ctx.get + registerSource 调用),dsh.client 元数据 inject 由 @deepseek-ai/dsh-client-ui-slash 迁移为 @deepseek-ai/dsh-client-ui-input-trigger——最终快照将输入触发服务与官方包一并更名,服务与 registerSource API 不变httpServer → webServer(lib/index.js 2 处:inject 数组 + ctx.webServer.register 调用)——最终快照将 host 侧 HTTP 路由服务更名,register({ kind: 'prefix', path, handler }) API 不变snapshots/20260812T172954Z-final)与 npm rc.5(@deepseek-ai/dsh@0.0.1-rc.5)consumer 实机 boot 验证通过(boot 清单包含本插件、client.js 返回 200、webServer 上传路由加载成功)dshClient 声明迁移为嵌套 dsh.client(inject 原样保留)——0810 的 ClientModuleHostService 只读 pkg.dsh.client,旧字段会被静默忽略导致插件不进 boot 图==== DSH_PASTE_INPUT_V1 ==== 标记协议)自动折叠为 📎 文件 chip;你在 chip 前后输入的文字按原顺序穿插保留(多文件发送时文字与各文件的 chip 逐段交错,chip 独占一行),悬停 chip 显示完整原始附件块(路径/清单/文件列表),点击 chip 复制完整路径+/-/0/Esc 快捷键、工具栏可复制完整路径;输入框待发送 chip 与气泡内已发送 chip 均支持(宿主端按所有权标记校验后回读已发送文件)<会话工作区>/.dsh/tmp/attachments/<session>/<send>/,绝对路径随消息前置给模型,无权限问题配合 dsh-external/dsh-vision 插件(注册 view_image 工具,桥接任意 OpenAI 兼容 VLM,默认智谱免费 glm-4.6v-flash),本插件的粘贴/拖拽截图可以直接识别:
view_image → VLM 返回图片内容(OCR 提取文字、读图表、识别 UI 布局等)两个插件零耦合:本插件负责"文件进对话",dsh-vision 负责"看图",通过工作区附件路径衔接。
附件块以显式标记界定(模型可见文本,气泡折叠识别用):
==== DSH_PASTE_INPUT_V1 ====
<附件根目录绝对路径>
Files: N
Manifest: .dsh-paste-input.json
Attached files (paths are relative to the root above):
- "file.txt" (2.0 KiB)
==== END DSH_PASTE_INPUT ====
仅支持标记格式(历史无标记消息不折叠)。标记前后各带空行,保证用户输入的文字与标记不在同一行。
文件名 作为相对路径存储——需要原路径的场景请使用拖拽或选择文件/文件夹按钮# 方式一:git 依赖固定 tag(公开镜像,推荐;也可用 github:lhh010/dsh-paste-input)
dsh plugin --profile web add '@dsh-community/dsh-paste-input@github:lhh010/dsh-paste-input#v0.2.7'
# 方式二:本地 link
# dsh plugin --profile web add link:/path/to/dsh-paste-input
并在 ~/.dsh/profiles/web/cordis.patch.yml 追加(热重载,无需重启):
- insert:
- id: dsh-paste-input
name: '@dsh-community/dsh-paste-input'
安装提示:pnpm 11 首次安装可能拦截 node-pty 等构建脚本——在
~/.dsh/profiles/web下执行pnpm approve-builds --all放行后重跑安装命令;装完硬刷新浏览器(Ctrl/Cmd+Shift+R)。
把下面这段提示词发给任意一个 DSH 会话,模型会替你完成安装:
帮我安装 dsh-paste-input 插件(DSH 文件输入增强:粘贴/拖拽文件),步骤:
- 执行
dsh plugin --profile web add '@dsh-community/dsh-paste-input@github:lhh010/dsh-paste-input#v0.2.7'(首次可能被 pnpm 11 拦截 node-pty 构建脚本而失败)- 在
~/.dsh/profiles/web下执行pnpm approve-builds --all(放行构建脚本)- 再执行一次第 1 步的安装命令
- 完成后在
~/.dsh/profiles/web/cordis.patch.yml追加 - insert 插件行(id: dsh-paste-input,name: '@dsh-community/dsh-paste-input'),并提醒我硬刷新浏览器(Ctrl/Cmd+Shift+R) 遇到报错先查 https://github.com/lhh010/dsh-paste-input README 的常见问题/已知限制。
hip 全链路可用;0811 与 0812 最终快照实机 boot 验证通过(见下)。
兼容 DSH
dsh-v0.1.2-alpha.3(无构建面,实机验证;纯客户端)
本插件无需迁移:运行时仅依赖 react 与 slots / conversation / sessions / inputTriggers 服务及 conversation.input.left / conversation.input.dock / settings.section 槽位——这些服务与槽位在 0.1.2-alpha.1 全部保留,客户端 API 重构(@deepseek-ai/dsh-client-runtime 移除、ConversationSnapshot 视图化、ctx.slots.inject 注册范式)不触及本插件的自包含 bundle;直接安装最新 tag(#v0.1.9)即可。
npm 发版兼容:兼容 DSH npm 发版 @deepseek-ai/dsh@0.1.1-rc.1(v0.1.5 实机 boot 验证:dsh --profile web 启动后 boot 清单包含本插件、/plugins/@dsh-community/dsh-paste-input/client.js 返回 200,依赖的 inputTriggers/conversation.input 门面与四个槽位在 0.1.1-rc.1 上保持不变)与 @deepseek-ai/dsh@0.1.0-rc.8(v0.1.4 实机验证,适配要点见下节),同时兼容 @deepseek-ai/dsh@0.0.1-rc.5(dist-tag next,即最终快照 snapshot0812 的 npm 发版;npm exec -p @deepseek-ai/dsh@0.0.1-rc.5 -- dsh --profile web --port <port> 可访问指定版本并启动,lib 生产模式)与 @deepseek-ai/dsh@0.0.1-rc.2(snapshot0811 的 npm 发版)。实测(npm rc.5 基线):dsh web 启动后 window.__DSH_BOOT__ 清单包含 @dsh-community/dsh-paste-input(inject: dsh-client-runtime/dsh-client-ui-input-trigger/dsh-client-ui-conversation/dsh-client-ui-settings),/plugins/@dsh-community/dsh-paste-input/client.js 返回 200;client 半经 window.__ModuleLoader__.load 正确注册,host 半的 webServer 上传路由在 rc.5 consumer 中加载成功。本插件无任何 cordis 依赖(无 peerDependencies;lib 构建产物无 cordis 导入)——0811 的 cordis 更名(cordis → @deepseek-ai/cordis)与本插件零影响,npm install 无需额外参数。
@deepseek-ai/dsh@0.1.0-rc.8,v0.1.4)@ + label,见 referenceDraftText)。v0.1.3 的 dock 删除逻辑只切除 1 个字符,点击 × 后 dock chip 消失但输入框内残留 📎 image.png … 之类的纯文本。v0.1.4 改用 input.consumeToken({ kind: 'span', span: { start: occurrence.offset, end: occurrence.offset + occurrence.length, draftRev } })(rc.8 SessionInputShell 的官方删除动词,带 CAS 保护)整段移除;无 consumeToken 的旧版本回退为按 occurrence.length 切除的 setDraft。insertReference 支持官方 appearance 字段(file/folder/session,官方 @file 引用源即用 appearance: 'file'),composer 内联 chip 由官方样式渲染(隐藏 @ 字形 + 官方文件图标 + 蓝色文件名)。v0.1.3 自造的 📎 emoji 前缀 + 8 字符截断 label 会渲染成「蓝色 @ + 回形针 + 蓝色文件名」,v0.1.4 移除 emoji 前缀,label 改为纯文件名(与官方 @file 引用一致),并附带 appearance: 'file'。conversation.input.left / conversation.input.dock / conversation.input.right(kind: 'list', scope: 'session')与 settings.section 在 rc.8 保持声明;inputTriggers.registerSource、conversation.input.for(actx)(返回带 state/insertReference/consumeToken/setDraft 的 facade)、host 侧 webServer.register 均不变。气泡折叠(DSH_PASTE_INPUT_V1 标记协议)与上传路由不受影响。dsh.plugin.json 清单 + resolveClientPath(packages/plugin/plugin)已删除,改为 package.json 的 dshClient 声明(platform: 'web',可选 inject/immediately)+ exports["./client"] 指向构建产物;宿主扫描 loader 条目组成 boot 图,Web 端从 /plugins/<id>/client.js 拉取。本插件 package.json 已满足该声明,无需改动。==== DSH_PASTE_INPUT_V1 ==== 标记)与 .dsh/tmp/attachments/<session>/<send>/ 目录逻辑不依赖快照内部实现,0809 实测全链路成功。dshClient 包的构建产物,缺失会抛 ClientPackageCompositionError 并拒绝启动 dsh web——升级快照或改源码后必须重新 pnpm run build 再启动,否则浏览器拉到的是旧 lib/client.js。dsh.client(packages/client/modules/src/index.ts 的 resolveMeta,pkg.dsh.client);顶层 dshClient 字段读不到会静默丢出 boot 图——无日志、无报错,"启动顺利但插件全没"。本插件已从顶层 dshClient 迁移为嵌套 dsh.client(inject 原样保留);lib/client.js 构建产物不变(package.json 不参与编译),symlink 安装改源仓库即生效,无需重装。cordis@4.0.0-rc.7 更名为 @deepseek-ai/cordis@4.0.1-rc.1(官方 client 包随之全部改从 @deepseek-ai/cordis 导入)。本插件不导入 cordis(无 peerDependencies、lib 构建产物无 cordis 引用),无需任何迁移。snapshots/20260811T152241Z)web 启动后 window.__DSH_BOOT__ 清单包含 @dsh-community/dsh-paste-input(inject: dsh-client-runtime/dsh-client-ui-slash/dsh-client-ui-conversation/dsh-client-ui-settings),/plugins/@dsh-community/dsh-paste-input/client.js 返回 200。本插件使用的槽位 conversation.input.left/conversation.input.dock(ui-conversation 声明)与 settings.section(ui-settings 声明)在 0811 上保持声明;slash 服务与 window.__ModuleLoader__ 加载协议不变。slash → inputTriggers:最终快照将输入触发服务由 slash 更名为 inputTriggers(随官方包 @deepseek-ai/dsh-client-ui-slash → @deepseek-ai/dsh-client-ui-input-trigger 一并改名,服务与 registerSource API 本身不变)。本插件 lib/client.js 已同步迁移 4 处(两个 inject 数组 + ctx.get + registerSource 调用),dsh.client 元数据的 inject 列表同步由 dsh-client-ui-slash 迁移为 dsh-client-ui-input-trigger。httpServer → webServer:最终快照将 host 侧 HTTP 路由注册服务由 httpServer 更名为 webServer(packages/host/webserver 提供,register({ kind: 'prefix', path, handler }) API 不变)。本插件 lib/index.js 已同步迁移 2 处(inject 数组 + ctx.webServer.register 调用),上传路由照常注册。cordis → @deepseek-ai/cordis 更名(npm rc.5 基线上为 4.0.1-rc.4)零影响,npm install 无需额外参数。snapshots/20260812T172954Z-final)web 启动后 window.__DSH_BOOT__ 清单包含 @dsh-community/dsh-paste-input;npm rc.5 consumer dsh web 启动后 boot 清单同样包含本插件(inject 已显示 dsh-client-ui-input-trigger),/plugins/@dsh-community/dsh-paste-input/client.js 返回 200,host 半 webServer 上传路由加载成功。本插件使用的槽位 conversation.input.left/conversation.input.dock(ui-conversation 声明)与 settings.section(ui-settings 声明)在最终快照与 rc.5 上保持声明;inputTriggers 服务与 window.__ModuleLoader__ 加载协议不变。CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: drag-and-drop、file-upload。