🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

输入历史召回 lhh010/dsh-input-history

DeepSeek Harness
lhh0108 天前有提交已提供中文文档扫描:含敏感能力

DSH Web 输入历史插件:Ctrl+Up / Ctrl+Down 像终端一样召回与切换已发送消息,零核心改动

36.2/100
综合分
3
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/29 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

该插件未发布到 npm,按作者文档从 GitHub 源安装即可(静态检查只覆盖 npm 路径,不代表插件不可用)。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add lhh010/dsh-input-history
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么[目录]—
dsh 原生插件 · dev
暂无时间戳·判据 →
装得上吗[实装验证]✓
本站已真实安装成功
非静态推断
L4 · 真实安装等级说明 →
数据截至 2026/09/28·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/05·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 8 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →

可信度证据

安装兼容性检查需源码安装

仓库 package.json 标记 private,未发布到 npm,需从源码安装

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包@dsh-external/dsh-input-history(未发布到 npm,仅可源码安装)
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/11/1 10:26:10

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 32 处,展示前 32 条)
  • 执行外部命令固定命令
    lib/index.js:91
    execFile("git", [
  • 读取本地文件
    lib/index.js:135
    const manifest = JSON.parse(readFileSync(resolve(dirname(argv1), "..", "package.json"), "utf8"));
  • 发起网络请求
    lib/index.js:167
    compatInflight = fetch(COMPAT_URL, { signal: AbortSignal.timeout(COMPAT_TIMEOUT_MS) }).then(async (res) => res.ok ? parseCompat(await res.json()) : vo
  • 执行外部命令固定命令
    lib/index.js:195
    const child = spawn("pnpm", ["add", `${PACKAGE_SPEC}@github:${MIRROR}#${tag}`], {
  • 读取本地文件
    lib/index.js:259
    return createHash("sha256").update(readFileSync(p)).digest("hex");
  • 发起网络请求
    lib/client.js:218
    const res = await fetch(`/${UPDATE_ID}/latest`, {
  • 请求外部主机api.github.com
    lib/client.js:238
    const res = await fetch(`https://api.github.com/repos/${MIRROR}/tags?per_page=10`, {
  • 发起网络请求
    lib/client.js:238
    const res = await fetch(`https://api.github.com/repos/${MIRROR}/tags?per_page=10`, {
  • 请求外部主机raw.githubusercontent.com
    lib/client.js:254
    const res = await fetch(`https://raw.githubusercontent.com/${MIRROR}/main/package.json`, { signal: AbortSignal.timeout(8e3) });
  • 发起网络请求
    lib/client.js:254
    const res = await fetch(`https://raw.githubusercontent.com/${MIRROR}/main/package.json`, { signal: AbortSignal.timeout(8e3) });
  • 发起网络请求
    lib/client.js:317
    const res = await fetch(`/${UPDATE_ID}/update`, {
  • 写入剪贴板
    lib/client.js:423
    navigator.clipboard?.writeText(updatePrompt(tag)).then(() => {
  • 写入剪贴板
    lib/client.js:431
    navigator.clipboard?.writeText(updatePrompt(tag)).then(() => {
  • 发起网络请求
    src/client/update-check.ts:25
    const res = await fetch(`/${UPDATE_ID}/latest`, { method: 'GET', signal: AbortSignal.timeout(9000) })
  • 请求外部主机api.github.com
    src/client/update-check.ts:40
    try { const res = await fetch(`https://api.github.com/repos/${MIRROR}/tags?per_page=10`, { headers: { accept: 'application/vnd.github+json' }, signal:
  • 发起网络请求
    src/client/update-check.ts:40
    try { const res = await fetch(`https://api.github.com/repos/${MIRROR}/tags?per_page=10`, { headers: { accept: 'application/vnd.github+json' }, signal:
  • 请求外部主机raw.githubusercontent.com
    src/client/update-check.ts:43
    try { const res = await fetch(`https://raw.githubusercontent.com/${MIRROR}/main/package.json`, { signal: AbortSignal.timeout(8000) }); if (!res.ok) re
  • 发起网络请求
    src/client/update-check.ts:43
    try { const res = await fetch(`https://raw.githubusercontent.com/${MIRROR}/main/package.json`, { signal: AbortSignal.timeout(8000) }); if (!res.ok) re
  • 发起网络请求
    src/client/update-check.ts:101
    const res = await fetch(`/${UPDATE_ID}/update`, { method: 'POST', headers: { 'content-type': 'application/json', 'x-dsh-plugin-update': 'click' }, bod
  • 写入剪贴板
    src/client/update-chip.ts:70
    void navigator.clipboard?.writeText(updatePrompt(tag))
  • 写入剪贴板
    src/client/update-chip.ts:76
    void navigator.clipboard?.writeText(updatePrompt(tag))
  • 执行外部命令固定命令
    src/update-endpoint.ts:41
    execFile('git', ['ls-remote', '--tags', REPO_GIT], { encoding: 'utf8', maxBuffer: 1024 * 1024, timeout: GIT_TIMEOUT_MS, killSignal: 'SIGKILL' }, (erro
  • 读取本地文件
    src/update-endpoint.ts:77
    const manifest: unknown = JSON.parse(readFileSync(resolve(dirname(argv1), '..', 'package.json'), 'utf8'))
  • 发起网络请求
    src/update-endpoint.ts:112
    compatInflight = fetch(COMPAT_URL, { signal: AbortSignal.timeout(COMPAT_TIMEOUT_MS) })
  • 执行外部命令固定命令
    src/update-endpoint.ts:129
    const child = spawn('pnpm', ['add', `${PACKAGE_SPEC}@github:${MIRROR}#${tag}`], { cwd: dshHomePath('profiles', 'web'), shell: true })
  • 读取本地文件
    src/update-endpoint.ts:152
    return createHash('sha256').update(readFileSync(p)).digest('hex')
  • 读取本地文件
    sync-mirrors.mjs:25
    const pkg = JSON.parse(readFileSync('package.json', 'utf8'))
  • 执行外部命令固定命令
    sync-mirrors.mjs:29
    const git = (...args) => execFileSync('git', args, { stdio: ['ignore', 'inherit', 'inherit'] })
  • 执行外部命令固定命令
    sync-mirrors.mjs:30
    const gitOut = (...args) => execFileSync('git', args, { encoding: 'utf8' })
  • 读取本地文件
    sync-mirrors.mjs:36
    if (!existsSync(doc)) continue
  • 读取本地文件
    sync-mirrors.mjs:37
    const text = readFileSync(doc, 'utf8')
  • 写入本地文件
    sync-mirrors.mjs:45
    writeFileSync(doc, next)
扫描于 2026/11/5(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
涉及外部主机:api.github.com、raw.githubusercontent.com

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

社区实装还没有人打卡 · 装过的第一个就是你
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-api-session-controller@deepseek-ai/dsh-client-ui-chat@deepseek-ai/dsh-client-ui-conversation@deepseek-ai/dsh-invariants@deepseek-ai/cordis@deepseek-ai/dsh-home-paths@deepseek-ai/dsh-host-webserver
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • Ctrl+上下键召回历史
  • 切换已发送消息
  • 零核心改动

README

由 DeepSeek 最新模型翻译生成
dsh-input-history 兼容 DSH dsh-v0.1.6-alpha.1(typecheck + 18 单测全绿,实机验证;0.1.2-alpha.1 起持续兼容) DSH Web 输入历史插件:像终端一样用 Ctrl+Up / Ctrl+Down 召回和切换已发送的消息,零核心改动。 你的 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 及以前):无可用版本 安装(profile 模式) 安装方式(v0.1.23 起自动挂载):本包自 v0.1.23 起自带 cordis.patch.yml 并声明 dsh.bundle.patch——dsh plugin --profile web add 安装后自动注册 profile 层并挂载,不再需要手写 insert 配置行(固定旧 tag 的部署仍需)。
展开完整文档(README 剩余 1 节)
dsh-input-history

兼容 DSH dsh-v0.1.6-alpha.1(typecheck + 18 单测全绿,实机验证;0.1.2-alpha.1 起持续兼容)

DSH Web 输入历史插件:像终端一样用 Ctrl+Up / Ctrl+Down 召回和切换已发送的消息,零核心改动。

你的 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 及以前):无可用版本

安装(profile 模式)

安装方式(v0.1.23 起自动挂载):本包自 v0.1.23 起自带 cordis.patch.yml 并声明 dsh.bundle.patch——dsh plugin --profile web add 安装后自动注册 profile 层并挂载,不再需要手写 insert 配置行(固定旧 tag 的部署仍需)。GUI 注意:插件页「添加插件」只接受注册表包名或本地目录路径;name@github:owner/repo#tag 是 pnpm 别名规格(CLI 专用),粘进 GUI 会报 ERR_PNPM_INVALID_PACKAGE_NAME——GUI 请克隆后用本地目录路径,或等 npm 发布后用包名。

方式一:git 依赖固定 tag(公开镜像,推荐;也可用 github:lhh010/dsh-input-history)
dsh plugin --profile web add '@dsh-external/dsh-input-history@github:lhh010/dsh-input-history#v0.1.27'

方式二:本地 link(开发)
git clone https://github.com/lhh010/dsh-input-history.git
cd dsh-input-history && pnpm install && pnpm run build
dsh plugin --profile web add link:/path/to/dsh-input-history

配置行($DSH_HOME/profiles/web/cordis.patch.yml,热重载,无需重启):

- insert:
- id: dsh-input-history
name: '@dsh-external/dsh-input-history'

安装提示:pnpm 11 首次安装可能拦截 node-pty 等构建脚本——在 ~/.dsh/profiles/web 下执行 pnpm approve-builds --all 放行后重跑安装命令即可;装完硬刷新浏览器(Ctrl/Cmd+Shift+R)。

智能版本门控更新提示 / DSH-gated update chip

更新浮标会结合当前运行的 DSH 版本(宿主端从 dsh 安装清单读取)与仓库根的 compatibility.json(版本→支持的 DSH 列表,精确匹配)判定提示形态:

- 最新版支持当前 DSH → 正常「新版本 vX 可用,点击更新」;
- 最新版需要更高 DSH、但存在支持当前 DSH 的中间新版 → 提示更新到中间版,并注明「另有 vX 需更高 DSH」;
- 最新版需要更高 DSH、且当前 DSH 无任何可用新版 → 琥珀色信息条:「新版本 vX 支持更高 DSH 版本,当前 DSH vY 暂不可用」,不提供直接升级。

兼容数据拉取失败或无该版本条目时,自动回退为旧的普通升级提示(离线安全)。发版时需同步维护 compatibility.json(与版本表/变更记录同一步骤新增一行)。

提示词安装(让 DSH 自己装)

把下面这段提示词发给任意一个 DSH 会话,模型会替你完成安装:

帮我安装 dsh-input-history 插件(DSH 输入历史召回插件(Ctrl+Up/Ctrl+Down 终端式输入历史)),步骤:
1. 执行 dsh plugin --profile web add '@dsh-external/dsh-input-history@github:lhh010/dsh-input-history#v0.1.27'(首次可能被 pnpm 11 拦截 node-pty 构建脚本而失败)
2. 在 ~/.dsh/profiles/web 下执行 pnpm approve-builds --all(放行构建脚本)
3. 再执行一次第 1 步的安装命令
4. 完成后提醒我硬刷新浏览器(Ctrl/Cmd+Shift+R)遇到报错先查 https://github.com/lhh010/dsh-input-history README 的常见问题/已知限制。

(npm 发版不再发布 cordis 名义的 vendored 包),本插件已迁移(peer 声明 @deepseek-ai/cordis: ^4.0.1-rc.1,npm rc.5 基线上为 4.0.1-rc.4),纯 npm install 不再报 ERESOLVE。

dsh-v0.2.1-rc.1 兼容要点(v0.1.27)

- 声明支持 dsh-v0.2.1-rc.1(0.2.1 系首个候选版,整合 alpha.1–5 全部插件面变更;升级实机验证:web profile --dump-config 全插件行加载零错误;运行时只读探测 file-trace mermaid/katex 路由 200、better-sidebar fence 活;宿主保留 webStartup 服务、无 alpha.5 之外的插件面破坏性变更;零适配改动);双 bundle node --check 通过

dsh-v0.2.1-alpha.5 兼容要点(v0.1.26)

- 声明支持 dsh-v0.2.1-alpha.5(升级实机验证:web 配置档 --dump-config 全插件行加载零错误;运行时只读探测 file-trace mermaid/katex 路由 200、better-sidebar fence 活;宿主保留 webStartup 服务、无插件面破坏性变更——新增的 conversation.input.model.label Slot 为并列新增键,与本插件既有注入面(conversation.input.for / conversation.input.dock 等)无冲突;零适配改动);双 bundle node --check 通过

dsh-v0.2.1-alpha.4 兼容要点(v0.1.25)

- 声明支持 dsh-v0.2.1-alpha.4(升级实机验证:web 配置档 --dump-config 全插件行加载零错误;宿主保留 webStartup 服务、无插件面破坏性变更——新引入的 engines.dsh 兼容判定仅对声明者生效,本插件未声明故沿用原有规则;六插件零适配改动);双 bundle node --check 通过

dsh-v0.2.1-alpha.3 兼容要点(v0.1.24)

- 声明支持 dsh-v0.2.1-alpha.3(升级实机验证:web 配置档 --dump-config 全插件行加载零错误;运行时只读探测 file-trace mermaid/katex 路由 200、better-sidebar fence 活;宿主保留 webStartup 服务,六插件零适配改动);双 bundle node --check 通过

dsh-v0.2.1-alpha.2 兼容要点(v0.1.23)

- 修复:自带 bundle 声明:补齐 cordis.patch.yml 并声明 dsh.bundle.patch——dsh plugin --profile web add 装完自动注册并挂载配置档层,不再需要手写 insert 行(社区反馈「GUI 安装后不生效」的根因);双 bundle node --check 通过

dsh-v0.2.1-alpha.2 兼容要点(v0.1.22)

- 声明:支持 dsh-v0.2.1-alpha.2(升级实机验证:web 配置档 --dump-config 全插件行加载、peer 校验零错误,宿主启动监听正常,零适配改动);双 bundle ode --check 通过

dsh-v0.2.1-alpha.1 兼容要点(v0.1.21)

- 声明:支持 dsh-v0.2.1-alpha.1(升级实机验证:web 宿主七插件挂载激活正常,零适配改动);typecheck/25 单测/构建全绿

dsh-v0.2.0-rc.2 兼容要点(v0.1.20)

- 声明:支持 dsh-v0.2.0-rc.2(升级实机验证,零适配改动);typecheck/25 单测/构建全绿

dsh-v0.2.0-rc.1 兼容要点(v0.1.19)

- 声明:支持 dsh-v0.2.0-rc.1(升级实机验证,零适配改动);typecheck/25 单测/构建全绿

dsh-v0.1.7-rc.2 兼容要点(v0.1.18)

- 声明:支持 dsh-v0.1.7-rc.2(npm 升级实机验证:六插件挂载激活正常,零适配改动);typecheck/25 单测/构建全绿

dsh-v0.1.7-rc.1 兼容要点(v0.1.17)

- 声明:支持 dsh-v0.1.7-rc.1(零适配改动);typecheck/25 单测/构建全绿

dsh-v0.1.7-alpha.2 兼容要点(v0.1.16)

- 新功能:新增更新浮标(此前本插件无更新提示机制)——含 DSH 版本门控(宿主端点 + 三态浮标 + 一键更新提示词)
- 验证:typecheck/25 单测/构建全绿;实机 0.1.7-alpha.2 验证

dsh-v0.1.6-alpha.2 兼容要点(v0.1.15)

适配 dsh 0.1.6-alpha.2 多实例重构:主会话改由 uiSession.current({ key, ctx })解析(alpha.1 的 sessions.list.current 字段已移除,此前导致 Ctrl+↑/↓ 静默失效);chat 视图链路全程可选 + console 诊断。typecheck/18 单测/构建全绿,alpha.2 实机验证恢复。

dsh-v0.1.6-alpha.1 兼容要点(v0.1.14)

声明支持 dsh-v0.1.6-alpha.1(npm 已发布,钉版本实机验证;client 插件面零代码差异,typecheck/18 单测全绿,实机加载正常)。安装命令统一更新为 #v0.1.27。

dsh-v0.1.5-rc.2 兼容要点(v0.1.13)

- 声明:rc.1 为 0.1.5 系列首个候选版本,client 插件面零代码差异;npm 已发布,钉版本实机验证
- 验证:typecheck/build/18 单测全绿;热挂载实机验证(后台运行状态 + Token 用量面板为 v0.10.0 新增功能,与本声明同版发布)

dsh-v0.1.5-alpha.2 兼容要点(v0.1.12)

- 验证:alpha.2 改动为 Sidebar 文档预览、模型文件交付、minimal 默认工具调整与 fs-ext 安装修复,client 插件面零代码差异;npm 已发布,钉版本实机验证;typecheck/build/18 单测全绿,启动清单确认加载

dsh-v0.1.5-alpha.1 兼容要点(v0.1.11)

- 验证:0.1.5 改动在会话格式 V3 / ctx.agent 移除 / 宿主 client bundle 服务路由改 /plugins/?? 组合路由,client 插件面零代码差异;npm 已发布,钉版本实机验证;typecheck/build/单测全绿,启动清单确认加载

dsh-v0.1.3-alpha.2 兼容要点(v0.1.10)

- 验证:alpha.2 改动全在 pi-ai / Web 顶栏 / 子代理消息 / host 面,client 插件面零代码差异;npm 已发布,钉版本实机验证;typecheck/build/单测全绿。本节以上版本(0.1.2-alpha.1~rc.1、0.1.3-alpha.1)同样兼容

dsh-v0.1.3-alpha.1 兼容要点(v0.1.9)

- 验证:0.1.3 的破坏性变更集中在 host/session 侧(SessionHandle / session format v2),client 插件面零代码差异;npm 未发布,源码宿主实机验证;typecheck/build/单测全绿。本节以上版本(0.1.2-alpha.1~rc.1)同样兼容

dsh-v0.1.2-rc.1 兼容要点(v0.1.8)

- 验证:alpha.5→rc.1 为纯版本号提交(252 文件零代码差异);实机 rc.1 验证通过,无需代码改动。本节以上版本(alpha.1~alpha.5)同样兼容

dsh-v0.1.2-alpha.1 兼容要点(v0.1.4)

- 服务面迁移:旧 @deepseek-ai/dsh-client-runtime/client 包已删除。本插件类型迁移到 @deepseek-ai/cordis(Context)、@deepseek-ai/dsh-api-session-controller/client(ISessions)与 @deepseek-ai/dsh-client-ui-conversation/client(IConversation/SessionInput/ConversationNode),并通过 @deepseek-ai/dsh-client-ui-chat/client 的声明合并读取 chat 视图快照类型。
- 历史来源迁移:会话快照不再携带 nodes。历史提取改走 Conversation 装配服务:ctx.uiConversation.binding(sessionId).snapshot.getSnapshot().views.get('chat')?.legacy.nodes(chat 视图的 legacy 兼容投影,user 节点结构不变,kind === 'user' 过滤与文本块拼接逻辑无需改动)。
- 输入门面保留:conversation.input.for(actx).setDraft() 与 input.state.getSnapshot().draft 契约在 ui-conversation 的 Lexical 输入外壳(SessionInputShell)上保留;setDraft 自身把光标置于末尾,插件不再手动搬运 caret。
- 编辑器 DOM 变化:composer 由 textarea 改为 contenteditable div(data-composer-input,仍位于 data-input-scroll 内)。目标判定放宽为「位于 data-input-scroll 内的元素」;草稿读取一律取输入机 published 的 clipboard 投影(contenteditable 的 DOM 文本无法还原 reference chip)。
- 注册范式:插件导出 inject = ['sessions', 'uiConversation', 'conversation'],apply 内直接读 ctx.sessions / ctx.uiConversation,不再使用 ctx.inject([...], scope => ...) 包装;dsh.client.inject 同步为 api-session-controller / ui-chat / ui-conversation 三个包名边。
本插件 v0.1.4 起内置兼容性自诊断:apply 时探测所需服务面(sessions/uiConversation),不满足时不再崩溃,而是在页面右下角渲染修复指引横幅(点击可关闭)。

0809 兼容要点(实机验证)

- 加载机制变化:0809 重构了客户端插件机制——旧的 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 已满足该声明,无需改动。
- 依赖的官方输入门面 conversation.input.for(actx).setDraft() 与 ConversationSnapshot.nodes 会话快照在 0809 上保留,契约未变;键盘 capture 拦截不依赖任何槽位。
- 构建要求:0809 宿主在激活时校验 dshClient 包的构建产物,缺失会抛 ClientPackageCompositionError 并拒绝启动 dsh web——升级快照或改源码后必须重新 pnpm run build 再启动,否则浏览器拉到的是旧 lib/client.js。

0810 兼容要点(snapshot0810)

- 元数据发现变化:0810 的 ClientModuleHostService 在启动时扫描已加载插件的 package.json,但只读嵌套 dsh.client(packages/client/modules/src/index.ts 的 resolveMeta,pkg.dsh.client);顶层 dshClient 字段读不到会静默丢出 boot 图——无日志、无报错,「启动顺利但插件全没」。本插件已从顶层 dshClient 迁移为嵌套 dsh.client(inject 原样保留);lib/client.js 构建产物不变(package.json 不参与编译),symlink 安装改源仓库即生效,无需重装。

0811 兼容要点(snapshot0811,实机验证)

- cordis 更名(本快照唯一影响本插件的官方变化):0811 把 vendored cordis 从 cordis@4.0.0-rc.7 更名为 @deepseek-ai/cordis@4.0.1-rc.1(官方 client 包随之全部改从 @deepseek-ai/cordis 导入)。本插件对 cordis 只有 type-only 导入(src/index.ts、src/invariant.ts 的 import type { Context } from 'cordis'),构建产物(lib/.js)零 cordis 运行时导入——更名不影响已构建 bundle 的运行时加载;但源码对 npm rc.2 基线 typecheck 时 cordis 裸导入报 TS2307(仅此一处),把类型导入迁移为 from '@deepseek-ai/cordis' 后全绿。建议同步把 peerDependencies.cordis 迁移为 @deepseek-ai/cordis: ^4.0.1-rc.1。
- 实机 boot 验证:snapshot0811(snapshots/20260811T152241Z)web 启动后 window.__DSH_BOOT__ 清单包含 @dsh-external/dsh-input-history(inject: dsh-client-runtime/dsh-client-ui-conversation),/plugins/@dsh-external/dsh-input-history/client.js 返回 200;typecheck(含 tests)对 0811 基线通过。依赖的输入门面 conversation.input.for(actx).setDraft() 与 ConversationSnapshot.nodes 契约在 0811 上保持不变(0811 会话快照仅新增 views 字段,不影响 nodes 读取)。

0.1.1-rc.1 兼容要点(npm 发版 @deepseek-ai/dsh@0.1.1-rc.1,v0.1.2)

- 实机 boot 验证:dsh --profile web(npm 0.1.1-rc.1)启动后 window.__DSH_BOOT__ 清单包含 @dsh-external/dsh-input-history(inject: dsh-client-runtime/dsh-client-ui-conversation),/plugins/@dsh-external/dsh-input-history/client.js 返回 200;依赖的输入门面 conversation.input.for(actx).setDraft() 与 ConversationSnapshot.nodes 契约在 0.1.1-rc.1 上保持不变,Ctrl+Up / Ctrl+Down 行为无回归

0812/最终快照 兼容要点(snapshots/20260812T172954Z-final,实机验证)

- cordis 更名落地:本插件已把 type-only 导入(src/index.ts、src/invariant.ts 的 import type { Context } from '@deepseek-ai/cordis')与 peerDependencies 迁移至 @deepseek-ai/cordis(^4.0.1-rc.1;npm rc.5 基线上为 @deepseek-ai/cordis@4.0.1-rc.4)——构建产物(lib/.js)依旧零 cordis 运行时导入,npm rc.5 消费者 typecheck 全绿,npm install 无需 --legacy-peer-deps。
- invariants 源码包迁移(仅影响本地 typecheck):最终快照把 @deepseek-ai/dsh-invariants 源码包从 packages/support/invariants 移到 packages/runtime-diagnostics/invariants,devDependencies 路径已同步更新;服务名 invariants 与注册协议未变,运行不受影响。
- 实机 boot 验证:最终快照(snapshots/20260812T172954Z-final)web 启动后 window.__DSH_BOOT__ 清单包含 @dsh-external/dsh-input-history,/plugins/@dsh-external/dsh-input-history/client.js 返回 200;npm rc.5 consumer dsh web 启动后 boot 清单同样包含本插件。依赖的输入门面 conversation.input.for(actx).setDraft() 与 ConversationSnapshot.nodes 契约在最终快照与 rc.5 上保持不变(0811 新增的 views 与 InputState.imageIds 均不影响本插件读取的 nodes/draft 契约)。typecheck、build 与 18 个单测对最终快照基线通过。

功能

- Ctrl+Up:把最近一条已发送的用户消息填入输入框;连续按向上遍历更早的消息
- Ctrl+Down:向下遍历回更新的消息;回到最新位置时恢复你按 Ctrl+Up 之前未发送的草稿
- 裸方向键、Enter、Ctrl+Z/Y、斜杠菜单等全部原样放行——多行输入的光标移动不受影响(对应 dsh-external/issues#153 的约束)
- 历史来自当前会话快照的用户消息(自动去相邻重复、跳过空白),刷新页面后仍然可用
- 输入框被手动编辑、粘贴、或发送清空草稿后,浏览状态自动复位

安装(profile 模式)

方式一:git 依赖固定 tag(公开镜像,推荐;也可用 github:lhh010/dsh-input-history)
dsh plugin --profile web add '@dsh-external/dsh-input-history@github:lhh010/dsh-input-history#v0.1.27'

方式二:本地 link(开发)
git clone https://github.com/lhh010/dsh-input-history.gitsh
cd dsh-input-history && pnpm install && pnpm run build
dsh plugin --profile web add link:/path/to/dsh-input-history

配置行($DSH_HOME/profiles/web/cordis.patch.yml,热重载,无需重启): yaml
- insert:
- id: dsh-input-history
name: '@dsh-external/dsh-input-history'

安装提示:pnpm 11 首次安装可能拦截 node-pty 等构建脚本——在 ~/.dsh/profiles/web 下执行 pnpm approve-builds --all 放行后重跑安装命令即可;装完硬刷新浏览器(Ctrl/Cmd+Shift+R)。

提示词安装(让 DSH 自己装)

把下面这段提示词发给任意一个 DSH 会话,模型会替你完成安装:

帮我安装 dsh-input-history 插件(DSH 输入历史召回插件(Ctrl+Up/Ctrl+Down 终端式输入历史)),步骤:
1. 执行 dsh plugin --profile web add '@dsh-external/dsh-input-history@github:lhh010/dsh-input-history#v0.1.27'(首次可能被 pnpm 11 拦截 node-pty 构建脚本而失败)
2. 在 ~/.dsh/profiles/web 下执行 pnpm approve-builds --all(放行构建脚本)
3. 再执行一次第 1 步的安装命令
4. 完成后提醒我硬刷新浏览器(Ctrl/Cmd+Shift+R)遇到报错先查 https://github.com/lhh010/dsh-input-history README 的常见问题/已知限制。

构建 sh
pnpm install
pnpm run build # lib/index.js + lib/invariant.js + lib/client.js
pnpm run test # 纯逻辑单测
pnpm run typecheck

设计说明

- 纯浏览器端实现:无服务端行为(src/index.ts 是空壳),不向模型或会话日志注入任何内容
- 历史数据派生自 ConversationSnapshot.nodes(kind === 'user' 的文本块),不维护第二份状态
- 键盘在 document capture 阶段拦截,仅匹配 Ctrl+ArrowUp/ArrowDown 且焦点在会话输入框(data-input-scroll 内)时生效
- 草稿写入走官方输入门面 conversation.input.for(actx).setDraft(),与撤销/发送事务兼容

已知限制与后续工作

- 历史仅覆盖当前会话(按 issue #153 语义);跨会话/跨设备历史共享未实现
- 快照窗口外的旧消息不在召回范围内(窗口内必然包含最近发送的消息,实际影响很小)
- macOS 的 Cmd 修饰键未绑定(可扩展为配置项)
- 切换会话后浏览状态复位,不会跨会话续接
预览分享卡片长什么样 ↓lhh010/dsh-input-history
分享 · DeepSeek Harness Hub
lhh010/dsh-input-history

DSH Web 输入历史插件:Ctrl+Up / Ctrl+Down 像终端一样召回与切换已发送消息,零核心改动

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部