在输入框粘贴大段文本时自动保存为附件文件;装了 dsh-better-sidebar 时,药丸上的「查看」可在侧栏编辑器打开并保存回原文件。
安装
# npm 包(预构建)
dsh plugin --profile web add dsh-auto-paste
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:sakuraqqq/dsh-auto-paste
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
A DeepSeek Harness plugin generated by
create-dsh-plugin(tool template) and extended with a web client paste listener. 由 create-dsh-plugin 生成并扩展的 DeepSeek Harness 插件:输入框大段粘贴自动存为附件文件。
Release / 发布状态
- npm:npm 页面 —— 官方源
registry.npmjs.org。发版策略:新版本先发到dist-tag: next观察,再人工转为latest——npm i dsh-auto-paste装到的就是当时的latest。本版0.1.5:一个包同时兼容 dsh0.1.5线与0.1.7线。 - 源仓库:
https://github.com/sakuraqqq/dsh-auto-paste(tag 与版本号一一对应)。 - 许可:MIT(见下)。
- 同步提示:npm 发布后国内镜像(npmmirror)同步有几秒到几分钟延迟,以官方 registry 为准。
License / 许可
MIT License — Copyright (c) 2026 misakamaster。 本插件以 MIT 许可开源:可自由使用、修改、再分发(含商用),需保留版权声明与许可文本。详见 LICENSE。 反馈(bug/建议)欢迎提交:QQ 群测试反馈或直接联系作者。
What it does / 功能
Web 客户端粘贴钩子(主路径) —
dsh.client.platform: web。在输入框粘贴超过阈值(默认 500 字符)的文本时:- 客户端拦截粘贴事件,通过现有 connection RPC(
/api→ Typert gateway)调用宿主pasteStore/savePaste; - 宿主把文本写入当前会话工作区的
pastes/<时间戳>.txt; - 输入框里插入 dsh 原生原子引用卡片(与 dsh 自己的附件同一套节点):
- 只显示文件名 + 字符数(
📄 20260815-103000.txt · 1234 字符),不显示路径; - 一键删除:Backspace / Delete 一次把整张删掉——它是 Lexical 装饰节点(
contenteditable="false"),不存在被逐字删的中间态; - 点击即在右侧栏打开全文(官方侧栏对
.txt走纯文本预览,只读;要能编辑需装 dsh-better-sidebar,见下); - 发送后消息里是同一张可点卡片。模型侧不塞正文:卡片序列化出来就是
@"pastes/20260815-103000.txt"这个引用,dsh-file-reference明确该语法不增加请求 token,模型据此自己去读那个文件。
- 只显示文件名 + 字符数(
- 降级(自动,无提示):拿不到上面那套输入框接口时——老 dsh 线、输入框正忙(提交中)、或光标在你打字期间被改动——退回文本引用
@"pastes/20260815-103000.txt" (1234 字符):发送后同样渲染成可点卡片,只是输入框里是纯文本、要手工删。两条路径给模型的文本完全一致。 - 其中 N 是 UTF-16 code units(即 JS 的字符串长度:emoji/代理对算 2,CJK 算 1),与 UTF-8 字节数不是一回事——这个口径是冻结的,已发消息里的引用数字不会被改写。卡片上的数字走卡片自己的显示字段,不进引用本身(引用必须是裸的
@"路径",否则点击时会把数字当成路径的一部分而打不开)。 - 保存失败时会尝试把原始文本插回输入框,并如实说明是否插回成功:插回去了就说已按原样粘贴;没插回去会明说「没能自动插回、内容仍在剪贴板,请手动 Ctrl+V 重试」,不做未经验证的承诺。
- 超过 1 MiB 的文本会被服务端拒绝(大小上限,防资源耗尽):报错并回退为普通粘贴,不落盘。
- 客户端拦截粘贴事件,通过现有 connection RPC(
save_paste 工具(纪律兜底) — 宿主同时注册
save_paste工具,模型在用户贴大段文字时可主动调用,把文本持久化为pastes/<时间戳>.txt并在回复中引用路径。工具输出只含path/bytes/chars(不含本机绝对路径,RPC 结果同样收窄:绝对路径含用户名与目录结构,仅宿主内部使用)。建议在项目AGENTS.md加一行纪律:## dsh-auto-paste 纪律 用户粘贴大段文字(约 500 字符以上)时:若输入框钩子未拦截,主动调用 save_paste 工具 把文本存入 pastes/<时间戳>.txt,并在回复中引用该工作区相对路径,不要复述原文。
可选集成:dsh-better-sidebar(在侧栏编辑粘贴文件)
本插件不调用 better-sidebar 的 API,只探测它在不在(ctx.inject(['betterSidebar']),仅用于下面那行提示与设置页状态)。点粘贴卡片的动作由 dsh 内核路由:内核把卡片地址交给右侧栏,装了 better-sidebar 时它认领该地址、用它的编辑器打开 pastes/*.txt(可编辑);没装则落到 dsh 自带的只读纯文本预览。
因此:
- 没装时:第一次粘贴出卡片后会就地说明一次(一行提示,可关闭,关掉后不再出现);万一错过了,设置页 General 分区的「侧栏集成」一行会一直写着,装上后自动消失。
- ⚠️ 已知上游缺陷:better-sidebar 的编辑器保存时用的是工作区相对路径,而它的写接口要求绝对路径 ⇒ 直接保存会 400(
is not an absolute path)。这是上游 omdsh-dev/DSH-better-sidebar#646,与本插件无关;在它修好之前,从它的文件树/路径输入框打开同一文件即可正常保存(那条路会用绝对路径)。
与 dsh 自带文件面板的区别:自带面板能浏览工作区文件(包括
pastes/),但只读、改不了;装了 better-sidebar 才有编辑入口。两者的差别只在"能不能改",不在"能不能看"。
Install / 安装与激活
方式一:从 npm 安装(推荐)
npm i dsh-auto-paste # 最新版(dist-tag: latest);--save-exact 可锁版
npm i dsh-auto-paste@0.1.5 # 或指定版本(换成你要的版本号)
# 在插件父目录执行,以包名注册到目标 profile:
dsh plugin --profile web add dsh-auto-paste
dsh --profile web # 重启 web profile,观察: [dsh-auto-paste] host ready ...
# 刷新浏览器页面后,控制台可见: [dsh-auto-paste] client paste listener attached — threshold 500 chars until the host's config arrives
# 随后: [dsh-auto-paste] config from host: minChars=500 (deployment), maxBytes=1048576
方式二:本地目录安装(开发/调试)
# 在插件父目录(本仓库根)执行;相对路径锚定调用目录:
dsh plugin --profile web add ./dsh-auto-paste
dsh --profile web
改动插件后:pnpm install && pnpm run build(tsc → dist/),然后重启 dsh --profile web 并刷新页面。
官方桌面版(DeepSeek Harness 桌面应用):同样支持,但要在桌面版自己的 profile 上单独装一次(它不复用 web profile 的装配)——桌面版自带 CLI,在应用安装目录下执行:
set "DSH_HOME=%USERPROFILE%\.dsh" # 换成桌面版实际使用的 home(隔离启动器会改它)
resources\runtime\cli\bin\dsh.cmd plugin --profile desktop add dsh-auto-paste
桌面版是独立 dsh 线(如 0.2.0-rc.2)。若它的运行时版本超出本插件声明的 peer 范围,dsh 会拒绝加载该 bundle(表现为插件完全无输出、设置里也没有本插件的阈值项),需要精确版本豁免——用 dsh plugin --profile desktop allow-version dsh-auto-paste@<版本> --dsh-version <运行时版本> --accept-risk,它会在 profile 目录写一个 compatibility.json;--dsh-version 必须填它报错时给出的那个值。豁免是精确配对的,插件升级或 dsh 升级都不会继承。
minChars 有两个入口:Settings → General 的「大段粘贴阈值」(保存即生效、不用重启;旁边的「恢复默认」清掉这次覆盖),以及 cordis.patch.yml 的 row config(部署默认值,改完只需重启 dsh、不用重新构建)。用户设置优先,没设置时用部署默认值。
覆盖值存在哪里随 dsh 线而变,保存后都立即生效:0.1.5 存进 dsh 自己的设置文档;0.1.7 起 dsh 改成"从插件自己的 Config 投影",覆盖值写回 profile patch(同一个 cordis.patch.yml)—— 所以本插件把 minChars 声明为 schemastery 的 volatile 字段:没有它,dsh 不会为该插件生成表单,写入也会被拒。当前 dsh 无法在界面保存时(没有 settings 服务、或该线不支持 volatile),设置行会说明原因并禁用保存。
host 始终是唯一权威:客户端半身拿不到 row config(dsh 的 dsh.client 只认 platform/inject/external/immediately,启动图里不带 config),它在启动时、以及每次保存设置后,都用 pasteStore/getConfig RPC 取生效值;取不到时用 500 兜底并在控制台标出来源。maxBytes 只有 row config 一个入口(属部署口径)。
Verification without an API key / 无 key 验证
dsh --profile web --dump-config | grep dsh-auto-paste # 配置层含本行
dsh plugin --profile headless add ./dsh-auto-paste
dsh --profile headless "run a probe" # host 半身加载;模型调用会 MISSING_CREDENTIAL
Manifest checklist / 清单自查
-
dsh.bundle.patch→./cordis.patch.yml(dsh 加载插件的硬性要求,缺失只会被当作普通依赖安装) -
dsh.client.platform: web+exports["./client"]→dist/client.js -
exports["./typert"]→dist/typert.host.js(typert-loader 自动注册 remote 调用) - 代码无外发数据:插件不发起任何网络请求,只写工作区
pastes/下的本地文件 - DSH peer 范围两段并列(
^0.1.5-rc.1 || ^0.2.0-rc.2)——别改回单段:dsh 在挂载前用 semver 逐个校验@deepseek-ai/dsh/@deepseek-ai/dsh-*peer(带includePrerelease),任一不满足就整包拒绝加载。单段^0.1.x会拒掉 0.2 线(官方桌面版在跑 0.2.0-rc.2);写成区间(>=0.1.5-rc.1 <0.3.0)又会把没测过的 0.2.1+ 一并放行。并列两段 = 只放行实测过的线
Dependencies pinned / 依赖锁定
@deepseek-ai/dsh-tools:^0.1.5-rc.1 || ^0.2.0-rc.2(peerDependency — 两段并列,见上)@deepseek-ai/dsh-typert-protocol:^0.1.5-rc.1 || ^0.2.0-rc.2(peerDependency — 同上;RPC schema 那一层)@deepseek-ai/cordis:^4.0.1(peerDependency — host provides it; runtime import ofServiceresolves through the profile's node_modules).zod:^4.4.3(Typert host schema instances, same line as in-box host remotes).
Pitfalls / 坑(从真实 spike 提炼,防呆)
- Node version: DSH requires Node ^22.19.0 || >=24.0.0. Older Node (e.g. v22.17) only warns EBADENGINE but may hit runtime issues — upgrade if you can.
- Node 版本:DSH 要求 ^22.19.0 || >=24.0.0。旧版本(如 v22.17)只告警 EBADENGINE,不阻断,但建议升级。
- npm dist-tag trap (the big one):
@deepseek-ai/dsh-toolslatestis a STALE 0.0.1-rc.1; the real line is under thenexttag (0.1.0-rc.x). This scaffold pins the next-tag version for you — nevernpm i @deepseek-ai/dsh-toolsover it.- npm dist-tag 坑(最大):
@deepseek-ai/dsh-tools的 latest 是过期的 0.0.1-rc.1,正确版本在 next tag。本脚手架已锁 next 版本,勿再手动 npm i 覆盖。
- npm dist-tag 坑(最大):
- Version-line alignment: keep every
@deepseek-ai/dsh-*package on the same0.1.0-rc.xline so pnpm does not install two module copies.- 版本线对齐:所有 @deepseek-ai/dsh-* 包统一用同一 0.1.0-rc.x 线,避免 pnpm 装两份模块。
@deepseek-ai/cordisis a peerDependency: import onlytype { Context }where possible (erased at compile). At runtime the host hands youctx— theServicebase class import resolves through the profile's node_modules.- @deepseek-ai/cordis 是 peerDep:尽量只 import type(编译期擦除),运行时 ctx 由宿主传入。
- Pure ESM: package.json must set
"type": "module"; build withmodule: esnext+moduleResolution: bundlerto keep bare specifiers.- 纯 ESM:package.json 必须 "type": "module";tsc 用 module:esnext + moduleResolution:bundler 保留 bare specifier。
dsh plugin add <dir>anchors relative paths to the INVOKING directory — run it from the parent directory, not from inside the plugin.- dsh plugin add 的相对路径锚定调用目录——要在插件的父目录执行。
- A DSH peer mismatch is a SILENT total failure on the desktop build: dsh evaluates every
@deepseek-ai/dsh*peer before mounting a bundle, and a rejected bundle is skipped without a word — no host log, no client bundle request, no settings row. If the plugin "does nothing at all" on a newer dsh line (the desktop app runs its own line, e.g.0.2.0-rc.2), readpackage.jsonpeer ranges FIRST, then grant the exact-version exemption (see Install).- DSH peer 不匹配在桌面版上是完全静默的失败:dsh 在挂载 bundle 前逐个校验 peer,被拒的 bundle 被直接跳过——host 无日志、client bundle 不被请求、设置里也没有本插件的行。若插件在某条更新的 dsh 线(桌面版自带一条,如
0.2.0-rc.2)上"毫无反应",先看package.json的 peer 范围,再考虑精确版本豁免(见安装节)。
- DSH peer 不匹配在桌面版上是完全静默的失败:dsh 在挂载 bundle 前逐个校验 peer,被拒的 bundle 被直接跳过——host 无日志、client bundle 不被请求、设置里也没有本插件的行。若插件在某条更新的 dsh 线(桌面版自带一条,如
- In the bundle
cordis.patch.yml,nameis a package name (resolved via node_modules /$DSH_HOME/profiles/node_modules), not a relative path.- bundle 的 cordis.patch.yml 里 name 用包名(走 node_modules 解析),不要用相对路径。
- Registrations are effects:
ctx.tools.register()/ctx.on()auto-dispose on unload. Wrap your OWN resources (timers/connections) inctx.effect(() => { acquire; return cleanup }).- 注册是 effect:ctx.tools.register()/ctx.on() 卸载自动清理;自己的资源(timer/连接)要包 ctx.effect(() => {…; return cleanup})。
- Load order = service dependencies, never file order:
export const inject = ['tools']makes the plugin wait untilctx.toolsis ready.- 加载顺序靠服务依赖(inject),不靠文件顺序。
- Full end-to-end (model actually calls your tool) needs
DEEPSEEK_API_KEY; without it--verifyproves load/list/event, and the model call fails with MISSING_CREDENTIAL.- 端到端(模型真正调工具)需 DEEPSEEK_API_KEY;无 key 时 --verify 只能证明加载/列出/事件,模型调用会 MISSING_CREDENTIAL。
链接
同类插件
zhu1090093659/dsh-web#packages/dsh-task-board★ 8262
侧边栏多列任务看板:卡片交给真实 DSH 智能体会话执行,支持 cron 定时(Host 侧到点执行,关浏览器也生效)。
zhu1090093659/dsh-web#packages/dsh-web-all★ 8262
DSH Web UI 插件与皮肤合集:任务看板、git 图、右侧面板、远程移动端 UI、桌宠、实时 token 统计与皮肤中心。
omdsh-dev/DSH-better-sidebar★ 3943
侧边栏完整工作台:内置文件渲染编辑、终端、Git 与子代理,支持三方插件注册新 Tab。
ccch1mneyyy/dsh-TUI★ 3913
Claude Code 风格全屏终端 UI:像素鲸鱼顶栏、实时工作状态行、思考流式展开。
MeteorNOX/DeepSeek-Balance-Whale-Widget★ 3793
右下角常驻的小鲸鱼挂件:余额、今日已用与每轮对话消耗(含峰谷价),余额预警与今日预算的泡泡内容都可编辑;泡泡点击序列模块化自定义,支持并列加权 A/B、随机台词与随机图片;内置 30+ 厂商模板(OpenAI / OpenRouter / Kimi / 硅基流动 / 方舟 / 智谱 / MiniMax 等),按模型查余额与订阅额度;另有任务结束音效、导入音频、自定义角色与资源管理。数据全在本机,无遥测。
Devin-AXIS/deepseek-design#deepseek-idesign★ 1414
可视化设计工作室,支持网站、App 原型、海报、信息卡、报告和杂志的模板创建、元素编辑、选区级 AI 草稿衔接与导出。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。