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-reverse-mode

v0.3.5

Published

Reverse-engineering agent preset for DeepSeek Harness: a REA (rea-agents) MCP bridge mounted only by the 逆向模式 preset

Readme

dsh-reverse-mode

npm version license

DeepSeek Harness 的 「逆向模式」agent 预设:在标准工具箱之上挂载 REA(rea-agents)的逆向工程能力,并且只在选择该预设的会话里挂载。

本包是 dsh-rea(MIT,作者 JeremyWangCY)的二次开发分支:把它从"全局宿主插件"改造成 agent preset 子插件,并优先复用 harness 自带的官方 MCP 桥。

为什么不是给 dsh-rea 加开关

Agent preset 是每个会话独立的 Cordis 插件树:预设里挂载的插件,其 ctx.tools / ctx.systemPrompt 注册会继承预设的 scope,因此只对使用该预设的 Agent 可见。所以「只在逆向模式触发」不需要任何运行时布尔开关:

  • standard / ptc / minimal / cordis 会话完全不加载本插件,REA 的工具 schema 一次都不会出现;
  • 选了「逆向模式」的新会话才挂载桥接行、拉起 npx rea-agents、注册 mcp__rea__*(官方桥)或 rea__*(内置桥)工具;
  • 现有会话保持它们创建时的组合,切换预设只影响新建会话。

用哪个桥

本包有两条桥,配置项 bridge 默认 auto,但预设行预置的是 builtin(原因见下):

| | 官方桥(@deepseek-ai/dsh-mcp-client) | 内置桥(lib/mcp-stdio.js) | |---|---|---| | 工具筛选 | ❌ 没有 allow-list,注册全部 ~170 个 | ✅ entry(9) / navigate(30) / analyze(17) / 显式数组 | | REA 的 $defs/$ref schema | ❌ 原样注册,pi-ai 的 legacy 投影会丢 $defs → 部分模型 HTTP 400 | ✅ 注册前把 $defs 内联进 properties | | 模型侧 schema 成本 | ~436 kB ≈ 10.9 万 token / 次请求(全量) | 全量内联后 ~547 kB ≈ 13.7 万 token;entry ~11 kB ≈ 2.8k token | | 工具名前缀 | mcp__rea__… | rea__… | | 追加能力 | SDK 分页、工具表变化订阅、注册失败整代回滚、canonical structuredContent/图片保真、取消与超时细化 | 体积小、零依赖、只实现用到的 MCP 子集;同样清理环境变量(丢弃 KEY/PASSWORD/SECRET/TOKEN 与 DSH_*) | | 来源 | harness 自带;运行时从 ~/.dsh/profiles/node_modules 解析到宿主那一份(不复制、不新增依赖) | 本仓库 |

auto 的规则:只有没有筛选需求时(tools: all 或 null)才选官方桥;请求了层级名或数组一律走内置桥——否则官方桥会把 9 个工具悄悄放大到 170 个(约 39×)。官方桥解析不到时(例如 ~/.dsh 布局不同)自动退回内置桥并告警,只写日志、不会让预设挂载失败。

为什么预设默认用内置桥

REA 的 170 个工具里有 158 个用 $defs + $ref 写 schema。pi-ai 对不声明 strict tool sampling 的模型,会把工具 schema 投影成 { type, properties, required },把 $defs 丢掉,于是 $ref: "#/$defs/…" 变成悬空引用,provider 直接返回:

HTTP 400 {"model":"deepseek-flash"}

实测(opencode-go deepseek-flash-1017):原始 schema 200、legacy(丢 $defs)400、legacy + $defs 200。标准工具箱没有 $ref,所以只有逆向模式会撞上。内置桥在注册前内联引用,因此对 strict 与非 strict 模型都能用;官方桥没有这个钩子。

presets/reverse.patch.yml 预置 bridge: builtin + tools: all。想要省上下文的档位,把那一行改成 tools: entry;如果你的模型支持 strict tool sampling 且你更想要官方桥的能力,可显式设 bridge: official:

config:
  bridge: official
  tools: all

与上游 dsh-rea 的差异

| 方面 | 上游 | 本分支 | |---|---|---| | 挂载位置 | profile 顶层的宿主插件行(全局:所有会话都付 schema 成本) | 「逆向模式」预设的子插件行(scope 内:只有该预设付费) | | 模式提示 | 只有一条启动日志 | 额外的 scoped systemPrompt 段(lib/guidance.js):模式说明、目标路由、证据纪律、许可与执行边界,并跟随实际前缀(mcp__rea__ / rea__) | | 桥 | 官方 @deepseek-ai/dsh-mcp-client(v0.2 起) | 默认也走官方桥;解析不到时退回零依赖内置实现(lib/mcp-stdio.js) | | 工具面 | 全量 170(v0.2 起取消 tier) | 官方桥同样全量;内置桥可按层级筛选(lib/catalog.js 是上游 v0.1 目录的逐字快照,上游 v0.2 已删除该文件) | | 环境自检 | 无 | lib/environment.js + scripts/doctor.mjs:连接后调用 REA 的 doctor,只读地报告引擎现状,缺失时在日志与模式提示里给出安装指引 |

为什么需要"运行时解析":profile 插件用 dsh plugin add link:<dir> 安装时是符号链接,Node 的 ESM 解析会跟随到真实路径,裸模块名于是从本仓库目录解析——那里没有 harness 的包(~/.dsh/profiles/node_modules 不是工作区的祖先)。lib/official-bridge.js 因此用 createRequire 锚定启动器提供的共享 node_modules(它是指向 DSH 安装目录的符号链接),拿到宿主自己的那一份官方桥,因此本仓库仍然零依赖、仍然可以就地编辑。代价是锚点依赖 ~/.dsh 布局,所以这个函数永不抛错:解析失败就回退内置桥。

安装

已发布到 npm:

dsh plugin --profile web add dsh-reverse-mode

开发时也可以从源码以 link: 方式安装(改完直接生效,方便就地编辑):

git clone https://github.com/xingxue-ux/dsh-reverse-mode.git
dsh plugin --profile web add 'link:/absolute/path/to/dsh-reverse-mode'

插件管理器会把声明了 dsh.bundle 的包自动选中为 profile bundle,其 presets/reverse.patch.yml 随即在启动时 insert 出 preset-reverse-engineering 声明。也可以在 Web 侧边栏的 Plugins 页里安装同一个包名或本地路径。

安装后:重启或等 HMR 重载 → 新建会话 → 在预设选择里选「逆向模式」。

安装后自检(环境与逆向工具)

DSH bundle 没有安装钩子,所以本包提供一条只读的自检命令,安装完(或换机器后)跑一次:

npm run doctor                   # 中文报告
node scripts/doctor.mjs --json   # 机器可读
node scripts/doctor.mjs --local  # 不启动子进程,离线最快

它先调用 REA 自带的 rea doctor(权威、与 version 绑定),失败时退回本地快速探测(只读环境变量与常见安装路径),并标明结论来自哪一侧。报告分两部分:

  • 必需:Node 版本、REA 能否经 npx 拉起;归档 / 安装包 / JavaScript / Electron / 托管程序集分析不需要分析引擎。
  • 原生二进制深挖(可选引擎):Hopper / Ghidra / IDA 的现状、解锁的能力与安装指引。

缺失引擎不会让模式不可用,只影响原生二进制的伪代码、反编译与交叉引用;把引擎接进来只需在 rea-bridge 行加 env(改完重载即生效,无需重启):

- id: rea-bridge
  name: dsh-reverse-mode
  config:
    env:
      GHIDRA_INSTALL_DIR: /opt/ghidra_12.1.1_PUBLIC      # Ghidra 12.1.x,需要 JDK 21
      # HOPPER_LAUNCHER_PATH: /Applications/Hopper Disassembler.app/Contents/MacOS/hopper
      # REA_IDA_MCP_CONFIG: /path/to/ida-mcp-registration.json

引擎由使用者自备并自行授权(Ghidra 免费;Hopper / IDA Pro 需商业授权)。本包不安装、不升级任何引擎,npm run doctor 也只读取环境。除手动运行外,插件会在 REA 连接成功后自动做一次同样的检查:缺失时在宿主日志写下 dsh-rea: environment check: no native analysis engine found …,并把「无原生引擎、如何启用」并入模式系统提示;已就绪时只记一条 info,提示段不加环境说明(避免无谓的 token)。

配置

编辑 presets/reverse.patch.yml 里 rea-bridge 行的 config(改完需重载):

| 字段 | 默认值 | 含义 | |---|---|---| | enabled | true | 设为 false 时保留挂载但不注册工具、不拉 REA 进程 | | bridge | 'auto' | auto / official / builtin;见上节。auto 只在 tools: all/null 时用官方桥 | | tools | 'entry' | 层级名 entry(9) / navigate(30) / analyze(17)、REA 工具名数组,或 'all' / null 表示全量。只有在内置桥下才生效:官方桥没有 allow-list,会注册全部 ~170 个(~10.9 万 token/次);预设行现在预置 all + builtin | | version | '6.4.0' | 固定的 rea-agents 版本,保证工具名与 schema 稳定 | | runner | 'npx' | 启动 REA 的包运行器(两条桥都用它) | | env | {} | 追加给 REA 子进程的环境变量(如 REA_ANALYSIS_PROVIDER) | | toolCallTimeoutMs | 300000 | 单次工具调用超时;原生分析可能很慢 | | startupTimeoutMs | 120000 | 首次 npx 下载 + initialize 握手 + tools/list 的预算 | | guidance | true | 是否注册「逆向模式」系统提示段 | | checkEnvironment | true | REA 连接成功后做一次环境自检(复用 REA 的 doctor),结果写日志并(无引擎时)并入模式提示;只读、非致命 | | environmentCheckTimeoutMs | 60000 | 单次环境自检的预算;超时只影响这条报告 | | failOnStartupError | false | true 时 REA 起不来会拒绝激活该预设挂载;默认降级为「没有 REA 工具」 |

验证

  1. 新建「逆向模式」会话,问一句「你现在能调用哪些 REA 工具」,或直接让它调用 open_binary;
  2. 该会话的宿主日志应按顺序出现:
    • dsh-rea: bridge=official (…, serverName=rea, namespace=mcp__rea__) resolved from <路径>(或 bridge=builtin …);
    • dsh-rea: registered N/M REA tools (x%, ~yk model-visible bytes)(内置桥)/ 官方桥自己注册全部工具;
    • dsh-rea: environment check: …(无引擎时 warn,就绪时 info);
  3. 新建一个 standard 会话,确认工具表里没有任何 mcp__rea__ / rea__ 前缀的工具;
  4. 想单独确认环境:npm run doctor(安装后自检,见上;--strict 可在无引擎时返回 1)。

事后核查(直接读会话日志)

node test/read-session-log.mjs ~/.dsh/sessions/<workspace>/<session-id>/session.v4.jsonl.zstd --tools

输出给出该会话真实绑定的预设、REA 工具定义的数量与名单。三个容易误判的坑,这个脚本都绕开了:

  • 会话日志是多帧 zstd:zstdDecompressSync() 只解第一帧(即 session header),长会话会看起来只有 198 字节、一行、且"预设 = standard";
  • header 里的预设不可信:那是创建时刻写入的,真正生效的绑定在投影文件 ~/.dsh/storages/session_projcache/sessions/<id>.json 的 record.rows.agentPreset;
  • 字面统计 rea__ 会被对话正文污染:只要在会话里聊过 REA,字面命中就很高,但"工具是否注册给该会话"只能看 JSON 中的 "name":"mcp__rea__…"(官方桥)或 "name":"rea__…"(内置桥)+ "description" 形态。

注意事项

  • 原生分析需要外部引擎:Hopper / Ghidra / IDA 需自行安装并持有合法授权;静态 JavaScript/Electron 分析不需要引擎。
  • 官方桥必须来自"正在运行的这一份":解析锚点(DSH_PROFILE_DIR / DSH_HOME / ~/.dsh/profiles)逐个尝试后,还会把结果与 realpath(process.argv[1]) 推导出的运行中 DSH 安装做一致性校验;不在同一安装里的包会被跳过且永不执行(防"陈旧的 ~/.dsh/profiles 指向另一套 DSH")。检查在 import() 之前完成。
  • 降级是显式的,且不会静默断供:官方桥解析不到、或解析到却启动失败(版本不匹配、Config 变化等),都会写一条 warn 并自动改用内置桥;失败原因会一并打印(not usable (<原因>))。因此看到 bridge=builtin 就说明发生了降级——功能仍在,少的是官方桥的健壮性与 env 清理。注意官方桥路径会 await 首次连接(上游同款),所以预设激活会等 REA 起来或失败,而不是后台挂载后静默留空。
  • 官方桥下 tools 不生效:它会注册 REA 声明的全部 ~170 个工具(~436 kB ≈ 10.9 万 token/次)。要低成本的层级筛选,必须 bridge: builtin。
  • 官方桥 + 非 strict-tool 模型会 400:官方桥原样注册 REA 的 $defs/$ref schema,而 pi-ai 的 legacy 投影会丢掉 $defs,导致悬空引用(实测 opencode-go deepseek-flash-1017 返回 400 {"model":"deepseek-flash"})。因此预设默认 bridge: builtin;内置桥会在注册前内联引用。
  • 两条桥都会清理环境:名字匹配 KEY/PASSWORD/SECRET/TOKEN 的继承变量与 DSH_* 会被丢弃,只有你在 env 里显式写下的变量会传给 REA;引擎变量(GHIDRA_INSTALL_DIR、HOPPER_LAUNCHER_PATH、REA_IDA_MCP_CONFIG)不属于被清理的模式,照常生效。
  • 预设的子插件列表是完全替换式的:本文件的列表是标准预设的快照,DSH 升级后若标准预设新增插件,需要手动同步过来。
  • REA 自身可能提示结果超出 stdio 传输预算,此时用 export_evidence_bundle 或 REA CLI 取回:npx -y rea-agents@latest <command>(工具前缀依桥而定:官方桥 mcp__rea__,内置桥 rea__)。
  • 工具名与 version 绑定;内置桥下未知名字只告警并跳过,官方桥下工具表由 REA 的 tools/list 决定。

迭代这个包

改完 lib/*.js 后必须重启 dsh web(或重启 harness 进程)才生效:本 profile 的 hmr 行沿用 base bundle 的默认值 root: [],即只监听 profile manifest 与 patch 文件。patch 变化时 dsh-hmr 只比对内容后调 reconcileProfilePatches() 更新 Loader entries,不清 ESM loadCache,所以插件源码改动会在同一个 URL 上命中模块缓存、继续跑旧代码;配置改动(如预设行的 config)则能即时生效。

排查"预设加载失败"时,重启后终端会打印具体细节,格式为 <行 id> (<名字>): <detail>,例如 rea-bridge (dsh-reverse-mode): …。

想边跑边改源码,可给 hmr 行加 root: ["."],但会监听整个 profile 目录(含 node_modules),通常不值得。

许可与致谢

  • 本包:MIT,见 LICENSE。
  • 上游桥接 dsh-rea(MIT),本分支复制了其 lib/catalog.js(上游 v0.1 版本)并保留其桥接行为,特此致谢。
  • 官方 MCP 桥 @deepseek-ai/dsh-mcp-client 属于 DeepSeek Harness(MIT),不随本包分发:运行时从已安装的 harness 里解析并挂载。
  • REA 由 morluto 及其贡献者开发(MIT),本包不包含 REA 源码,也不提供任何商业反编译器授权。