ByteNoteByteNote
dsh 的 Python 包怎么发:从源码到 PyPI
字

字节笔记本

2026年10月6日 · 约 8 分钟读完

dsh 的 Python 包怎么发:从源码到 PyPI

API中转
¥120

DeepSeek 开源的智能体框架 DeepSeek Harness(命令行工具名 dsh)此前已经有过 Python SDK 的上手路径:装包、跑示例、嵌进自己的程序。但那是使用者的视角。真正想往仓库里提交代码、再把包发上 PyPI 的贡献者,面对的是另一套流程。官方在 python/development.md 里把它拆成了按成果选择的五条工作流:构建运行时产物、验证 SDK、针对 Node 源码运行、构建分发包,以及验证候选发行版。包本身的行为另见仓库里的 SDK 参考与运行时载体参考文档,本文只沿这条主线把要点整理出来。

运行时产物先落地

各平台可执行文件属于构建产物,不检入 git。在仓库根目录先跑 pnpm install,再执行 pnpm exec tsx scripts/build-exe-for-python-sdk.ts,脚本会把所选平台的载体写进 dist-exe/,并同步到 python/sdk-runtime/。所需的 lib/ 产物已存在时可以加 --skip-build 跳过重建;要挑选平台,就用 --targets=node24-linux-x64,node24-linux-arm64,node24-macos-arm64 这样的列表。macOS 构建还有一步特殊处理:同步 node-pty 依赖的 spawn 辅助程序。

dsh Python 贡献者工作流总览:五条流水线

用 uv 和 pytest 验证 SDK

SDK 验证有两条纪律:虚拟环境必须放在 python/ 目录之外,先装测试组再跑套件。把 UV_PROJECT_ENVIRONMENT 指向仓库外的路径之后,uv sync --project python/sdk --group test 安装依赖,uv run --project python/sdk pytest 执行测试。其中的 test_bundled_runtime.py 会逐个运行可用的内置载体,某个载体的产物还没构建时,对应用例自动跳过,不会红掉。仓库级的测试政策单独成文,这里只管 Python 侧。

想确认 SDK 真能跑通一轮对话,做一个交互式冒烟测试:在环境变量或仓库根目录 .env 里放好 DEEPSEEK_API_KEY,三行代码就能拿到最终回复:

python
from deepseek_harness import DeepSeekHarness

with DeepSeekHarness() as harness:
    print(harness.run("say hi").final_response)

两种源码开发载体

不想先构建、直接对着 Node 源码调试的贡献者有两条路。第一种是设置 DSH_RUNTIME_MODE=node,在系统 Node(不低于 22.19)上使用已构建的 Node 载体;构建脚本会刷新这个载体,但分发物绝不包含它,也不会自动选中它。第二种完全绕开构建:把仓库根目录设为工作目录,用 launch_args_override 指向 tsx 和未构建的 TypeScript 入口(packages/examples/jsonrpc-demo/src/bin.ts),默认配置不合用时再补一个 cordis=... 指定配置。完整的源码模式调用示例在 python/sdk/tests/manual_sdk_agent_smoke.py。

打包成 wheel

分发的版本号以根目录 package.json 为权威:暂存脚本把这个版本注入两个 Python 包,并把 SDK 固定到同版本的 deepseek-harness-runtime-bin。纯 SDK wheel 只需构建一次,运行时 wheel 则要在每个原生平台上各打一个,构建完可直接从本地目录安装验证:

sh
version="$(node -p "require('./package.json').version")"
python scripts/build-python-release.py --package sdk --output-dir dist-python
python scripts/build-python-release.py --package runtime --platform macos-arm64 --runtime-exe dist-exe/dsh-jsonrpc-agent-pkg-macos-arm64 --output-dir dist-python
pip install --find-links dist-python deepseek-harness-sdk=="$version"

运行时分发只提供 wheel。发布流水线最终上线四个包:一个纯 SDK wheel 加三个平台 wheel,覆盖 Linux x64、Linux arm64,以及 macOS 14 及以上版本的 arm64。python-v<仓库版本> 形式的标签只有在与仓库版本一致时才被接受;0.0.1-rc.1 这类预发布版本,在 wheel 文件名和元数据里会按 PEP 440 规范写成 0.0.1rc1。

上架前的干跑闸门

真正的发布走层层闸门。想在不碰 PyPI 的情况下验证候选发行版,有两条等价路径:给拉取请求打 python-release-dry-run 标签,或手动运行 GitHub 的 Release (Python) 工作流并把 publish 设为 false。两条路径都会构建全部四个 wheel,在 Python 3.10 和 3.14 上安装 Linux 发行集合,检查精确文件名与元数据,执行 PyPI 默认的单文件大小限制,最后保留一份带 SHA-256 哈希的汇总产物。关键在于两条路径都不持有任何注册表凭据,拉取请求的运行进不了任何发布作业。

发布闸门:干跑检查项与 publish=true 的四道条件

正式发布从私有自动化仓库运行,包元数据指向独立的只读公开源码镜像,镜像本身不运行发布 Actions。私有仓库把 PYPI_PUBLISHER_REPOSITORY 定义为自身的 owner/name,并把 PUBLIC_PYPI_RELEASE_ENABLED 保持为 false,只在有意的发布窗口切成 true。

运行时与 SDK 拆成两个独立作业还有一层考虑:SDK 上传失败后可以直接续跑,不必重发不可变的运行时文件。publish=true 只有在条件齐备时才被接受:工作流从配置的发布仓库、匹配的 python-v* 标签运行,受保护的 pypi-runtime 与 pypi 环境分别批准对应作业。PyPI Trusted Publishing 照常提供短期 OIDC 凭据,但公开 attestation 会暴露私有发布仓库的身份,所以被主动关闭。

三条边界划清楚

回头看这五条工作流,贯穿的是三条边界:产物不进 git,构建即同步;验证不污染源码目录,虚拟环境放仓库外;发布不走个人凭据,靠标签、受保护环境和显式开关放行。对想给自己项目搭 Python 发布流水线的团队,这套干跑加多闸门的设计值得直接搬走。

相关文章

分享: