DAP 复用器:将您的编辑器、REPL、调试器(等)连接在一起,全部协同工作于一个单一调试会话中,即使在工具故障时也能保持持久

Lobsters Hottest 工具

摘要

dap-mux 是一个 DAP 代理,允许您将多个 DAP 客户端(编辑器、REPL 等)连接到单个调试会话,从而实现从不同工具同时调试,具备会话持久性和延迟加入状态重放功能。

<p><a href="https://lobste.rs/s/afaweo/dap_multiplexer_connect_your_editor_your">Comments</a></p>
查看原文
查看缓存全文

缓存时间: 2026/06/02 19:36

dap-mux/dap-mux

来源:https://github.com/dap-mux/dap-mux

dap-mux

每个终端调试器都迫使你做出选择:要么使用拥有完整求值能力但缺乏源码上下文的 REPL,要么使用带有可视化断点但调试控制台功能受限的编辑器。dap-mux 消除了这种选择的必要。将你的编辑器和 REPL 同时连接到同一个调试会话。在你的 REPL 中单步执行,编辑器同时跟踪当前行。在暂停的栈帧中求值任意表达式。从任意一侧设置断点。

┌──────────────┐    ┌──────────────┐    ┌──────────────┐
│  Helix       │◄──DAP──►│              │◄──DAP──►│ debugpy     │
│  源码视图    │        │  dap-mux      │        │ (或任意      │
│  断点        │        │              │        │  DA 服务器) │
└──────────────┘        │              │        └──────────────┘
                        │              │
┌──────────────┐        │              │
│ 你的 REPL    │◄──DAP──►│              │
│  求值        │        └──────────────┘
│  单步执行    │
└──────────────┘

dap-mux 是一个 DAP 代理。它位于调试适配器和多个客户端之间,路由请求,广播事件,并向延迟加入的客户端重放会话状态。你的编辑器和 REPL 都是通过多路复用器共享同一会话的一等 DAP 客户端。

附带的 REPL 前端是一个 IPython 扩展——一个调试控制界面,为 IPython 的 %magic 接口提供 DAP 连接能力。这是作者使用的 REPL。其他 REPL 也可以连接到多路复用器;只是目前它们还没有内置的前端。

目标

你的编辑器 + 你的语言 + 你的调试器 + 你的REPL——以及你想连接的任何其他工具。你的工具选择应该可以自由组合。dap-mux 是连接器;工具是你的。以下承诺由此而来:

每一层边界都使用标准 DAP。 任何支持 DAP 的编辑器、REPL 或工具都可以连接到面向客户端的接口,无需特殊插件或配置。任何标准 DAP 适配器都可以在上游工作。每个连接点都使用标准协议。

每个连接的客户端都是一等的。 所有客户端都可以执行任何标准 DAP 操作:设置断点、单步执行、求值表达式、检查调用栈、选择栈帧。没有客户端是只读的。

会话在客户端变化时仍能存活。 连接或断开客户端不会中断会话或重启适配器。在会话中途连接第二个编辑器。断开 REPL 再重新连接。会话继续执行。

延迟加入者能看到当前状态。 初始化后连接的客户端会收到已初始化的握手信号,如果当前处于暂停状态,还会收到当前的停止位置。中途加入的编辑器会立即显示正确的代码行。

状态

v0.9.0 是第一个公开发布版本——这是除作者以外的人第一次能够运行这个工具。在此之前,它都是在私有环境中开发和测试的。核心机制——协议帧封装、序列号重写、多客户端路由、事件广播、延迟加入状态重放——已经过实际测试,并有一个测试套件覆盖。它所实现的工作流是真实的:将 Helix 或 VS Code 和一个 IPython REPL 连接到同一个 debugpy 会话,并同时在两者中进行调试。这是两个编辑器、一个调试适配器、一个 REPL,在两个平台上。

目标要求支持任何编辑器、任何语言、任何适配器——而这个领域的大部分还没有被任何人接触过。有很多东西需要发现和修复。Bug 报告、测试其他组合的人提供的说明,以及拓宽经过验证的基础的贡献,正是这个项目目前所需要的。

要求

uv (https://docs.astral.sh/uv/) — 它自动管理 Python 运行时。

debugpy 必须在目标环境中可用。dap-mux 通过 TCP 连接到它,从不直接导入它:

pip install debugpy   # 在你的项目的虚拟环境中

安装

uv tool install dap-mux

用于开发:

git clone https://github.com/dap-mux/dap-mux
cd dap-mux
uv sync --group dev

快速入门

此示例使用 Helix 和内置的 IPython 前端。任何支持 DAP 的编辑器都可以工作——参见编辑器设置

1. 启动会话

dmux script.py

dap-mux 启动 debugpy,连接多路复用器,并打开一个 IPython REPL:

dap-mux listening on 127.0.0.1:5679
Connect your editor to 127.0.0.1:5679

IPython 提示符出现。脚本已暂停——在编辑器客户端发送 configurationDone 之前不会开始运行。

2. 在 Helix 中设置断点,然后连接

在 Helix 中打开脚本,在你想要暂停的行上设置断点(b 或你配置的按键)。然后连接:

:debug-remote 127.0.0.1:5679 attach

在连接之前设置好断点。 当 Helix 连接时,它会发送 configurationDone,这会启动脚本。如果没有断点,脚本会在你做任何事之前运行完成。

执行开始并在你的断点处暂停。Helix 高亮当前行。IPython 打印暂停位置。

3. 从 IPython 调试

python
%bt                                # 调用栈
%eval results                      # 在暂停的栈帧中求值表达式
%frame 2                           # 切换到另一个栈帧(%eval 会跟随)
%n                                 # 单步跳过
%s                                 # 单步进入
%c                                 # 继续
%finish                            # 跳出当前函数
%break script.py:42                 # 设置断点

IPython 提示符下的裸 Python 会在本地执行。%eval 在调试目标帧中求值。


使用

启动模式

dmux script.py

启动 debugpy 并附加到 script.py,启动多路复用器,打开 IPython REPL。一个命令全部搞定。

附加模式

当 debugpy 已经在运行时:

dmux --attach 5678
dmux --attach 192.168.1.10:5678

IPython REPL 连接到现有会话。如果在你加入时会话已经暂停,使用 %sync 来发现当前的暂停状态。

无头模式

使用 --headless 启动多路复用器而不启动 IPython REPL。连接你自己的工具——任何编辑器、任何支持 DAP 的 REPL 前端。

dmux script.py --headless
dmux --attach 5678 --headless

什么启动什么:

在启动模式(dmux script.py --headless)下,dap-mux 启动 debugpy 并附加到 Python 脚本,启动多路复用器,然后等待。你可以连接你自己的客户端。

在附加模式(dmux --attach host:port --headless)下,dap-mux 连接到一个已经运行的调试适配器——任何语言、任何适配器。负责先启动适配器。

将 dap-mux 用于其他语言

多路复用器使用标准 DAP,可以与任何调试适配器一起工作。以下是一个使用 rdbg (https://github.com/ruby/debug) 的 Ruby 示例:

# 终端 1 — 启动 Ruby 调试适配器
rdbg --open --port 5678 script.rb

# 终端 2 — 启动多路复用器
dmux --attach 5678 --headless
# dap-mux listening on 127.0.0.1:5679

# 现在将你的编辑器连接到 127.0.0.1:5679 作为 DAP 服务器

任何支持 DAP 的编辑器都能立即连接。一个 REPL 前端——相当于为 Ruby、Julia 或其他语言提供的 IPython 扩展——目前还不存在,需要构建。多路复用器已经就绪;前端是贡献的所在。

CLI 参考

dmux [TARGET] [OPTIONS]

Arguments:
  TARGET          要调试的 Python 脚本(启动模式)

Options:
  --attach, -a TEXT        附加到正在运行的调试适配器([host:]port)
  --mux-port, -p INT       客户端连接端口(0 = 自动)[default: 0]
  --log-level, -l TEXT     日志级别:DEBUG, INFO, WARNING, ERROR [default: WARNING]
  --log-file TEXT          同时将日志写入此文件
  --headless               启动时不启动 IPython REPL
  --version, -V            显示版本并退出

编辑器设置

Helix

添加到 ~/.config/helix/languages.toml

[[language]]
name = "python"

[language.debugger]
name = "debugpy"
transport = "tcp"
command = "python3"
args = ["-m", "debugpy"]
port-arg = "--listen=127.0.0.1:{}"

[[language.debugger.templates]]
name = "launch"
request = "launch"
completion = [{ name = "script", completion = "filename" }]
args = { mode = "debug", program = "{0}" }

[[language.debugger.templates]]
name = "attach"
request = "attach"
completion = []
args = {}

使用 :debug-remote host:port attach 连接到正在运行的 dap-mux。此配置的工作副本位于 demos/helix/

VS Code

安装 Python Debugger (https://marketplace.visualstudio.com/items?itemName=ms-python.debugpy) 扩展 (ms-python.debugpy),然后添加到 .vscode/launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Connect to dap-mux",
      "type": "debugpy",
      "request": "attach",
      "connect": {
        "host": "127.0.0.1",
        "port": 5679
      }
    }
  ]
}

使用固定端口启动 dap-mux(dmux script.py -p 5679),以便启动配置可以硬编码端口。在运行配置之前在 VS Code 中设置断点——启动配置会发送 configurationDone 并开始执行。此配置的工作副本位于 demos/vscode/

Neovim

配置 nvim-dap 连接到 mux 端口作为 DAP 服务器。将 dap.adapters 指向 127.0.0.1:,类型为 "server"

其他编辑器

任何带有 DAP 客户端的编辑器都可以工作。将其配置为连接到 127.0.0.1: 作为现有的 DAP 服务器——dap-mux 使用标准 DAP,无需特殊配置。


IPython 扩展

dap-mux 附带一个 IPython 扩展,将 IPython 变为调试控制界面。使用 %load_ext dap_mux 加载它,或者使用 dmux(它会自动加载)。

魔法命令别名描述
%connect [host:]port连接到多路复用器
%disconnect断开连接
%sync发现当前暂停状态(在延迟加入一个已暂停的会话后很有用)
%bt调用栈
%frame N选择栈帧;随后的 %eval 在该帧的作用域中求值
%eval expr在当前帧中求值表达式
%step%s单步进入
%next%n单步跳过
%continue_%c继续执行
%finish跳出当前函数
%break file:line [cond]设置断点(可选条件)
%clear file:line移除文件中的所有断点

%eval 在调试目标帧中求值——它可以访问当前暂停点的局部和全局变量。常规的 IPython 表达式中求值是在本地作用域。


工作原理

每个 DAP 客户端(编辑器、REPL)通过 TCP 连接到 dap-mux。多路复用器重写序列号,使所有客户端共享一个到调试适配器的上游连接。响应会路由回发出请求的客户端。事件广播给所有连接的客户端。

当一个客户端在会话已经初始化后加入时,dap-mux 会重放缓存的 initialized 事件,如果当前会话处于暂停状态,还会重放最后一个 stopped 事件——这样延迟加入者无需重启适配器就能立即看到当前状态。

dap-mux 使用 Python 编写。该工具是一个网络 I/O 路由器——它从一个 TCP 连接读取 JSON 并写入其他连接——而 Python 的 asyncio 正是为此目的而构建的。实际性能上限是人类的按键速度;多路复用器永远不会成为 CPU 瓶颈。

IPython 集成是另一个原因:它在同一个进程中运行,可以直接访问 IPython 的内部。Go 或 Rust 实现必须通过 Python 壳程序并进行 IPC 才能实现同样的效果,这将用一个混乱的进程外设计来换取干净的进程内设计。


适合人群

  • 终端优先的开发者,使用 Helix、Neovim、Emacs 或任何支持 DAP 的编辑器,希望在不离开终端的情况下获得 IDE 级别的调试体验
  • 数据科学家,他们依赖 IPython,并希望在调试时获得可视化的源码跟踪
  • 远程开发者,通过 SSH 进行调试,图形化 IDE 不切实际
  • 任何人,曾希望自己的调试 REPL 有 tab 补全、历史记录和 import 功能

兼容性

编辑器

任何支持 DAP 的编辑器都可以用作显示客户端——将其连接到 mux 端口,就像连接任何其他 DAP 服务器一样。

编辑器DAP 集成状态
Helix内置已测试
VS Code内置已测试
Neovimnvim-dap (https://github.com/mfussenegger/nvim-dap)未测试
Emacsdap-mode (https://github.com/emacs-lsp/dap-mode)未测试
VimVimspector (https://github.com/puremourning/vimspector)未测试

语言

对于拥有功能强大的交互式 REPL 的语言来说,REPL + 编辑器工作流最为丰富。多路复用器本身可以与任何 DAP 适配器一起工作。

语言调试适配器REPL
Pythondebugpy (https://github.com/microsoft/debugpy)IPython ← 已测试
Rubydebug (https://github.com/ruby/debug) gemIRB, Pry
JuliaDebugAdapter.jl (https://github.com/julia-vscode/DebugAdapter.jl)Julia REPL
ElixirElixirLS (https://github.com/elixir-lsp/elixir-ls)IEx
JavaScriptjs-debug (https://github.com/microsoft/vscode-js-debug)Node.js REPL

对于 DAP 支持强大但缺乏有意义 REPL 的语言——Go (Delve)、Rust (codelldb)、C/C++ (lldb-dap)——仍然可以通过 dap-mux 受益于多编辑器会话和不重启断线重连。

dap-mux 针对 debugpy 进行了测试。其他适配器应该也能工作(DAP 是标准协议),但尚未验证。

平台

平台状态
Linux已测试
macOS已测试
Windows预期可用;尚未验证

这不是什么

dap-mux 是一个路由器,而不是调试器。 它在你的工具和你的调试适配器之间转发 DAP 消息。它不执行代码、不检查内存、也不理解你的程序状态。它所连接的一切已经具备这些功能——dap-mux 提供的是连接性,而不是功能。

它不会添加你的适配器本身没有的调试功能。 如果你的调试适配器不支持某些功能,dap-mux 不会提供它们。能力来自你带来的工具。dap-mux 负责连接它们。

终端优先设计。 没有 GUI,也不会有——在命令行中,唯一的实际交互就是启动它。之后,你就在你的编辑器和 REPL 中工作,而不是在 dap-mux 中。

IPython 扩展是 Python 专有的。 多路复用器适用于任何拥有 DAP 适配器的语言。附带的 REPL 集成构建在 IPython 之上,仅限 Python。其他语言的 REPL 可以是潜在的前端,但它们尚未构建。

dap-mux 是管道中的一个组件,而不是一体化工具。 如果你想要一个带有自己 UI 的自包含 TUI 调试器,pudb (https://github.com/inducer/pudb) 非常出色且积极维护。dap-mux 适用于另一种工作方式:你的编辑器擅长一件事,你的 REPL 擅长一件事,你的调试适配器擅长一件事——dap-mux 将它们连接起来。Unix 一直是这样工作的。

限制

  • 仅针对 debugpy 进行了测试。 其他调试适配器应该可以工作,但尚未验证。
  • Windows 支持未经测试。 代码没有已知的平台特定依赖,但尚未在 Windows 上验证。

许可证

MIT

贡献

欢迎提交问题和反馈。该项目还很年轻——你测试过的适配器或编辑器的错误报告和说明尤其有用。请参阅 CONTRIBUTING.md 了解如何设置开发环境、什么是有价值的 PR、以及项目会接受和不会接受什么。请参阅 CHANGELOG.md 了解变更记录。

相似文章

@dzhng: 你应该试试 duet agent 的 /relay:

X AI KOLs Following

duet-agent 是一个用于持久化 AI 代理任务的框架,这些任务可以跨越单个聊天会话,实现长时间运行、可恢复的任务,具有跨会话记忆和通过 relay 轮次观察到的状态。

ChromeDevTools/chrome-devtools-mcp

GitHub Trending (daily)

Chrome DevTools MCP 是一个开源的模型上下文协议服务器,允许 AI 编程助手(Gemini、Claude、Cursor、Copilot)控制并检查实时 Chrome 浏览器,用于自动化、调试和性能分析。它将 Chrome DevTools 与 Puppeteer 集成,为 AI 助手提供完整的浏览器检查和自动化能力。