npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-switch

v1.8.0

Published

Customizable switch buttons for the DSH Web GUI composer (one-click slash-command insertion into the draft, config stored in the Host settings document)

Readme

dsh-switch

English

DSH 插件 — 在 DSH Web GUI 聊天输入框左侧添加可自定义的快捷按钮。点击按钮把斜杠命令插入输入框,补充参数后手动发送。

功能

按钮只有一种行为(mode: "insert",单次插入):每次点击把 /命令 插入到输入框已有内容之前(内容为空时就是开头),再点再插。不执行任何宿主命令、没有常驻状态,视觉上是纯蓝色文字标签(无图标)。

  • 设置面板:Settings → "Switch Buttons",可添加、编辑、删除、启用/禁用按钮;底部动态展示当前会话可用的斜杠命令参考(中英双语)
  • 配置持久化:保存在当前 Host profile 的 dsh-switch 条目 config(cordis.patch.yml),清浏览器缓存不丢;localStorage 仅作首屏缓存
  • 旧配置自动迁移:早期版本的 toggle(开关命令)、persistent(持久插入)类型已移除,存量按钮读取时自动降级为单次插入(保留 command,丢弃 commandOff/projection),不会消失
  • settings.yaml 遗留段导入:从把配置存在 settings.yaml 的旧宿主(DSH Desktop 1.x / harness 布局)升级后的首次启动,会把旧 dsh-switch: 段导入本条目 config 一次(用 volatile legacyMigrated 标记去重),按钮不会因宿主升级丢失

安装

⚠️ profile 里已有 git 依赖(如 aegis)时不要跑 dsh plugin add:该 CLI 转调 pnpm,pnpm 解析 git 依赖时可能静默永久挂起。请用下面的路径 ②——不依赖 pnpm、无需联网。

① 桌面市场 / registry

dsh-switch 上 npm registry 后,直接在 DSH Desktop 插件市场安装/更新,或 dsh plugin --profile <profile> add dsh-switch——走宿主 generation 机制,自动更新可用。

② 一键安装脚本(免 pnpm、可离线)

git clone https://github.com/weimingyu9312/DSHSwitch.git
cd DSHSwitch
node install.mjs                       # 自动探测 DSH_HOME 与 web profile
node install.mjs --profile desktop     # DSH Desktop 2.x 用的是 desktop profile
node install.mjs --profile web --home <DSH_HOME> --dry-run   # 只预览不落盘

脚本定位 DSH_HOME(环境变量优先;否则按 ~/.dsh / %APPDATA%\dsh-desktop\harness / ~/Library/Application Support/dsh-desktop/harness / ~/.config/dsh-desktop/harness 顺序探测),把包体(含 vendored 依赖)复制进 <profile>/node_modules/dsh-switch/,并在 profile manifest 的两处登记(dependencies["dsh-switch"] 与 dsh.profile.bundles),写回一律 UTF-8 无 BOM;对 desktop profile 还会把 dsh-switch 从 dsh.desktop.desktopDeselectedBundles 移除,确保插件真正启用。脚本幂等,且绝不触碰 dsh.desktop.generationProjection(那是市场 staging 私有层)。装完重启 DSH Desktop 让 host 半加载。

③ 手工合并(附录)

把仓库(连同 node_modules/ vendor 树)复制到 <DSH_HOME>/profiles/<profile>/node_modules/dsh-switch/,再编辑 <DSH_HOME>/profiles/<profile>/package.json:在 dependencies 加 "dsh-switch": "file:./node_modules/dsh-switch",在 dsh.profile.bundles 数组追加 "dsh-switch",若 dsh.desktop.desktopDeselectedBundles 里有它则一并移除。保存为无 BOM UTF-8(PowerShell Set-Content -Encoding UTF8 会带 BOM 打断宿主 JSON 解析——用 [IO.File]::WriteAllText 或无 BOM 编辑器)。两处登记缺一不可,缺了宿主 reconcile 会跳过该 bundle。之后重启 DSH Desktop。

Host 运行依赖 @deepseek-ai/schemastery(连同传递依赖 @deepseek-ai/cosmokit 与纯类型的 @standard-schema/spec)既随 git 仓库入库(vendored 在 node_modules/ 下,clone 即用),又以正式 npm dependencies 声明(exact 锁版本,所以 registry 的 npm install dsh-switch 会自动带上)。vendored/锁定的版本必须与目标宿主发行版一致(当前 schemastery 3.18.4 / cosmokit 1.8.5 = DSH Desktop 2.0.17 / dsh 0.2.0-rc.2),升级时三个包要同步刷新。junction/git 安装形态下插件靠 vendored 树解析依赖——保留它,且不要换成符号链接(会产生 reparse 链导致启动失败,完整论证见 lib/index.js 头注释)。

registry 安装已自足:npm 会强制把一切 node_modules/ 路径剔出发布 tarball,所以 registry 副本没有 vendored 树;但自 v1.7.0 起三个包已声明为 dependencies,npm install dsh-switch 会把精确锁定的版本装进 profile 的 node_modules,Node 查找即可命中。一键安装脚本能识别这种布局并跳过 vendoring。

兼容性

| 契约 | 已验证宿主 | |------|-----------| | Host 半注册 dsh-switch Config(volatile buttons、settings.configure({auto:false})),Client 半经 configForms 服务读写;插槽 conversation.input.left + settings.section;composer face inputActions.setDraft + 标准 hook useInput | DSH Desktop 2.0.17(dsh 0.2.0-rc.2,desktop profile) | | 降级形态:插槽未下发 inputActions / 无 useInput(更老或非典型宿主) | 退回 execCommand('insertText') DOM 兜底通道与旧 input prop——可靠性下降但仍可用 |

最低支持:提供 inputActions face 的 dsh-web-app 构建(0.8.x 系);v1.8.0 的配置服务需要 configForms 客户端服务(dsh 0.1.7-rc.1+)。更旧的宿主拿不到配置(只有 localStorage 缓存),但按钮渲染不受影响。

使用

配置按钮

  1. 打开 DSH Web GUI → Settings → Switch Buttons
  2. 点击 "+ 添加按钮"
  3. 每张卡片两个字段:
    • 名称:按钮显示文本(如 "Plan Off")
    • 斜杠命令:要插入的命令(如 /plan off)
  4. 拨动开关启用/禁用;点击 × 删除

默认配置

{
  "buttons": [
    { "id": "plan", "label": "Plan", "command": "/plan", "mode": "insert", "enabled": true },
    { "id": "plan-off", "label": "Plan Off", "command": "/plan off", "mode": "insert", "enabled": true }
  ]
}

默认值只在 Host 配置里还没有 buttons 键时生效;用户改过一次后以存储为准。想恢复默认,删掉 profile cordis.patch.yml 里 - id: dsh-switch 条目的 config 并清除浏览器 localStorage 后重启。

配置字段

| 字段 | 类型 | 说明 | |------|------|------| | id | string | 按钮唯一标识 | | label | string | 按钮显示文本 | | command | string | 要插入的斜杠命令 | | mode | string | 固定 insert;旧值(toggle/persistent/无)读取时自动迁移 | | enabled | boolean | 是否启用 |

验证

  1. 输入框左侧出现 switch 按钮
  2. 点击 Plan 按钮:输入框为空 → /plan 出现在开头;已有内容(如 research pricing)→ 变成 /plan research pricing;按 Enter 正常发送
  3. 设置面板底部显示斜杠命令参考列表

命令没插进输入框时怎么查

浏览器控制台(F12)直接问插件它自己看到了什么:

__dshSwitch.state()                // scopeBound / buttons / faces / draft / editorFound / editorPhase
__dshSwitch.log()                  // 最近 40 次插入:kind(setDraft|dom|no-editor|skip:stale-snapshot|…)/text/before/after
__dshSwitch.insert("/plan")        // 手动跑一次插入,看草稿有没有出现命令

常见现象:faces: [] = 宿主插槽没下发 inputActions(老宿主版本),插入退回 DOM 兜底通道、可靠性下降;editorFound: false = 输入框 DOM 变了,两条通道都写不进;明细日志用 localStorage.setItem("dsh-switch-debug","1") 打开。

架构速览

| 文件 | 职责 | |------|------| | lib/index.js | Host 半:导出 dsh-switch Config schema(volatile buttons)、关闭宿主自动生成的配置表单、一次性导入旧 settings.yaml 的 dsh-switch: 段 | | lib/client.js | Client 半:按钮栏(注入 conversation.input.left 槽)、设置面板(注入 settings.section 槽)、经 configForms 服务的配置读写与迁移 |

插入的唯一行为是草稿写入(不执行命令):首选走宿主 composer face 的 inputActions.setDraft(命令 + 原草稿) —— 经编辑器自身 state 提交,不会被 Lexical 调和抹掉;草稿含引用 chip、提交机锁定、或该会话无 face 时退回 execCommand('insertText') 兜底。配置改动乐观渲染 + 写 localStorage 镜像 + 经条目 config(configForms.set("buttons", …) / Host settings.mutate)落盘。

开发

本仓库以 junction 链接装进 profile,改工作区文件即生效。插件分宿主/客户端两半,热更新不对称——判断"改了没生效"前先确认动了哪一半:

| 改动文件 | 需要的动作 | |----------|-----------| | lib/client.js(按钮栏、设置面板、插入逻辑) | 刷新浏览器页面即可 | | lib/index.js、package.json、cordis.patch.yml(host 半) | 完全重启宿主进程(dsh web Ctrl+C 重跑 / 彻底退出 DSH Desktop) | | 按钮配置(设置面板里改) | 无需任何动作——落 profile 条目 config 后即时生效 |

node test/client.test.cjs   # 或 npm test — 33 项 jsdom 行为测试(迁移规则、face 路由、chip/相位闸、退役符号回归)
node test/preview.cjs       # 离线渲染设置面板到 .preview/preview-{dark,light}.html 核对布局
node install.mjs --dry-run  # 发版前用假 DSH_HOME 验证安装脚本

发布历史见 CHANGELOG.md。

License

MIT